Changing the case of a string with awk

前端 未结 4 1471
死守一世寂寞
死守一世寂寞 2021-02-20 15:55

I\'m an awk newbie, so please bear with me.

The goal is to change the case of a string such that the first letter of every word is uppercase and the remaining letters ar

相关标签:
4条回答
  • 2021-02-20 16:06

    When matching regex using the sub() function or others (like gsub() etc), it's best used in the following form:

    sub(/regex/, replacement, target)
    

    This is different from what you have:

    sub("regex", replacement, target)
    

    So your command becomes:

    awk '{ for (i=1;i<=NF;i++) sub(/\B\w+/, substr(tolower($i),2), $i) }1'
    

    Results:

    Abcd Efgh Ijkl Mnop
    

    This article on String Functions maybe worth a read. HTH.


    I should say that there are easier ways to accomplish what you want, for example using GNU sed:

    sed -r 's/\B\w+/\L&/g'
    
    0 讨论(0)
  • 2021-02-20 16:06

    My solution will be to get the first part of the sub with a first substr insted of your regex :

    echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1 ; i <= NF ; i++) {sub(substr($i,2),tolower(substr($i,2)),$i)} print }'
    Abcd Efgh Ijkl Mnop
    
    0 讨论(0)
  • 2021-02-20 16:12

    The issue is that \B (zero-width non-word boundary) only seems to match at the beginning of the line, so $1 works but $2 and following fields do not match the regex, so they are not substituted and remain uppercase. Not sure why \B doesn't match except for the first field... B should match anywhere within any word:

    echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1; i<=NF; ++i) { print match($i, /\B/); }}'
    2   # \B matches ABCD at 2nd character as expected
    0   # no match for EFGH
    0   # no match for IJKL
    0   # no match for MNOP
    

    Anyway to achieve your result (capitalize only the first character of the line), you can operate on $0 (the whole line) instead of using a for loop:

    echo 'ABCD EFGH IJKL MNOP' | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2)) }'
    

    Or if you still wanted to capitalize each word separately but with awk only:

    awk '{for (i=1; i<=NF; ++i) { $i=toupper(substr($i,1,1)) tolower(substr($i,2)); } print }'
    
    0 讨论(0)
  • 2021-02-20 16:26

    You have to add another \ character before \B

     echo 'ABCD EFGH IJKL MNOP' | awk '{for (i=1;i <= NF;i++)
     {sub("\\B[A-Za-z]+",substr(tolower($i),2),$i)} print}'
    

    With just \B awk gave me this warning:

    awk: cmd. line:1: warning: escape sequence \B' treated as plainB'

    0 讨论(0)
提交回复
热议问题