AWK语句在代码中循环,以使某些字段大写

AWK语句在代码中循环,以使某些字段大写,awk,toupper,tolower,Awk,Toupper,Tolower,代码 awk '{for(i=1;i<=NF;++i){$i=toupper(substr($i,1,1))tolower(substr($i,2));}print}' tolower部分占据所有行,如果我通过某个字段(例如数字2)进行更改: $> echo 'Aaaa Bbbb Cccc DDDD Eeee Ffff Gggg HHHH' | awk '{print toupper(substr($0,1,1)) tolower(substr($2,2)) }' $>

代码

awk '{for(i=1;i<=NF;++i){$i=toupper(substr($i,1,1))tolower(substr($i,2));}print}'
tolower部分占据所有行,如果我通过某个字段(例如数字2)进行更改:

$>  echo 'Aaaa Bbbb Cccc DDDD Eeee Ffff Gggg HHHH'  | awk '{print toupper(substr($0,1,1)) tolower(substr($2,2)) }'

$>  Abbb

$0告诉第一个字符的所有行都要执行toupper,下面的部分($0)(,1,1)告诉它只执行一个字符,最后指定执行此操作的长度(1),但tolower部分说它从字段2的第二个字符中取出并一起打印(因为语句是粘贴的) 请告诉我,如果我在这方面的一些错误和解释希望可以理解

我希望做Toupper of Tolower的语句,指定要执行此操作的字段

预期的示例:

是否仅对该空格中的字段4和8大写,如前所示,或在其他示例中,如果我有以分号分隔的字段,如何执行此操作,示例:

>$ echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH'
在字段1的第4个单词和第3个字段的第2个单词中执行相同的操作。(现在字段以分号分隔)

结果:

Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh

或者您可以将它转过来,将整行转换为小写,然后在将第一个字符转换为大写的字段上循环,例如

awk '{
    sub($0,tolower($0))
    for (i = 1; i <= NF; i++)
        sub(substr($i,1,1),toupper(substr($i,1,1)))
}1'
$ echo 'aaaa bbbb cccc DDDD;eeee ffff;gggg HHHH' |
> awk -F'[ ;]' '{
>     for (i = 1; i <= NF; i++) {
>         if (i % 4 == 0) {
>             sub($i,tolower($i))
>             sub(substr($i,1,1),toupper(substr($i,1,1)))
>         }
>     }
> }1'
aaaa bbbb cccc Dddd;eeee ffff;gggg Hhhh
使用替代字段分隔符

根据您对问题的编辑,如果您有
“[;]”“
的备用字段分隔符,则可以在gawk中使用字符列表指定备用分隔符,或通过或使用分隔符来指定,例如

awk -F'[ ;]' '{
    sub($0,tolower($0))
    for (i = 1; i <= NF; i++)
        sub(substr($i,1,1),toupper(substr($i,1,1)))
}1'
在这种情况下,所有其他字段将保持不变,第4个和第8个字段将转换为滴定酶,例如

awk '{
    sub($0,tolower($0))
    for (i = 1; i <= NF; i++)
        sub(substr($i,1,1),toupper(substr($i,1,1)))
}1'
$ echo 'aaaa bbbb cccc DDDD;eeee ffff;gggg HHHH' |
> awk -F'[ ;]' '{
>     for (i = 1; i <= NF; i++) {
>         if (i % 4 == 0) {
>             sub($i,tolower($i))
>             sub(substr($i,1,1),toupper(substr($i,1,1)))
>         }
>     }
> }1'
aaaa bbbb cccc Dddd;eeee ffff;gggg Hhhh
$echo'aaaa bbbb cccc DDDD;eeee ffff;gggghhh'|
>awk-F'[;]''{
>对于(i=1;i如果(i%4==0){
>sub($i,tolower($i))
>sub(substr($i,1,1),toupper(substr($i,1,1)))
>         }
>     }
> }1'
aaaa bbbb CCC Dddd;eeee ffff;gggg HHH

如果这还没有涵盖所有内容,请告诉我。

请尝试以下内容。我尝试了一个非常通用的解决方案,其中我们可以提到字段值,其中我们需要将第一个字符作为大写,其余字符作为小写

echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' | 
awk -v convert="4,8,9" '
BEGIN{
  FS="[; ]"
  num=split(convert,array,",")
  for(i=1;i<=num;i++){
    found[array[i]]
  }
}
{
  for(i=1;i<=NF;i++){
    if(i in found){
      first=substr($i,1,1)
      second=substr($i,2)
      sub(first,toupper(first))
      sub(second,tolower(second))
    }
  }
}
1'
我在这里扩展了您的示例(通过添加1个测试值),您还可以以逗号分隔的形式提及
-v convert=“:4,8,9…”
中的所有字段号来更改它们



解释:为上述代码添加解释,它仅用于解释目的,我没有运行它来检查它是否与注释一起运行

echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' |      ##Printing strings with echo and sending its output to awk command.
awk -v convert="4,8,9" '                                         ##Starting awk program here and creating variable named convert whose value will be all fields where we need to make the changes with comma separated.
BEGIN{                                                           ##Starting BEGIN section here.
  FS="[; ]"                                                      ##Setting FS field separator as semi colon OR space here for all lines.
  num=split(convert,array,",")                                   ##splitting convert variable to array whose delimiter is comma.
  for(i=1;i<=num;i++){                                           ##Starting a for loop from i=1 to till value of num(which is total number of elements in array, above created)
    found[array[i]]                                              ##Creating array named found whose index is value of array[i].
  }
}
{
  for(i=1;i<=NF;i++){                                            ##Starting a for loop from value of 1 to till NF.
    if(i in found){                                              ##Checking if current field is same field which user wants to change, if yes then go ahead with further statements.
      first=substr($i,1,1)                                       ##Creating variable first whose value is 1st character of current field.
      second=substr($i,2)                                        ##Creating variable first whose value is from 2nd field to till complete value of current field.
      sub(first,toupper(first))                                  ##using sub for changing first to UPPER case.
      sub(second,tolower(second))                                ##using sub for changing second to LOWER case.
    }
  }
}
1'                                                               ##Mentioning 1 will print edited/non-edited lines here.
echo'Aaaa Bbbb Cccc ddddd;Eeee Ffff;Gggg HHHH weeeewrwr'|##使用echo打印字符串并将其输出发送到awk命令。
awk-v convert=“4,8,9”##在此处启动awk程序并创建名为convert的变量,该变量的值将是所有需要用逗号分隔的字段。
开始{##从这里开始开始开始部分。
FS=“[;]”##将所有行的FS字段分隔符设置为分号或空格。
num=split(convert,array,“,”)35;#将convert变量拆分为分隔符为逗号的数组。

对于(i=1;i因为
在字段1的第四个单词和第三个字段的第二个单词中做了相同的操作。
和其他答案以及您问题中的一些其他文本和示例建议您要将所选分号分隔字段的所选空格分隔子字段更改为以大写开头,然后全部为小写,这是一个ap方法:

$ cat tst.awk
BEGIN {
    split(nrs,tmp,/[ .]+/)
    for (i=1; i in tmp; i+=2) {
        tgtFldNrs[++numTgts]  = tmp[i]
        tgtSubFldNrs[numTgts] = tmp[i+1]
    }
    FS = OFS = ";"
    subFs = subOfs = " "
}
{
    for (tgtNr=1; tgtNr<=numTgts; tgtNr++) {
        fldNr    = tgtFldNrs[tgtNr]
        subFldNr = tgtSubFldNrs[tgtNr]

        numSubFlds = split($fldNr,subFlds,subFs)
        subFld = subFlds[subFldNr]
        subFlds[subFldNr] = toupper(substr(subFld,1,1)) tolower(substr(subFld,2))

        fld = subFlds[1]
        for (subFldNr=2; subFldNr<=numSubFlds; subFldNr++) {
            fld = fld subOfs subFlds[subFldNr]
        }
        $fldNr = fld
    }

    print
}
告诉awk更新字段1的子字段4(
1.4
)和字段3的子字段2(
3.2
)(在
中,对字段1的第4个单词和问题中的第3个字段的第2个单词执行相同操作),它将输出:

$ awk -v nrs='1.4 3.2' -f tst.awk file
Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh

希望这就是您想要做的,如果没有,请更新您的问题以澄清您的需求,并提供更全面的示例输入/输出。

您可以像下面这样尝试Perl

$ echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' | 
perl -0777 -nE ' @a=qw(4 8 9);%k = map {$_,1} @a; s/(\w+)/$i++; $k{$i}==1 ? "\u\L$1":$1/ge; print'
Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh Weeeeewrwr
或者还有一条路

$ echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' | 
perl -0777 -nE ' @a=qw(4 8 9);@k{@a}=undef; s/(\w+)/$i++; exists $k{$i} ? "\u\L$1":$1/ge ; print '
Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh Weeeeewrwr

可以使用
sed

  echo 'Aaaa Bbbb Cccc dDDD;Eeee Ffff;Gggg HHHH' | sed -r 's/([a-zA-Z]{1})([a-zA-Z]+)/\U\1\L\2/g'
解释:

  • -r
    :用于扩展常规支出

  • 's/../…/'
    :代表替换

  • ([a-zA-Z]{1})
    :查找单词的第一个字符

  • ([a-zA-Z]+)
    :单词的其余部分

  • \U\L
    :用于更改字符大小写的运算符

  • \1…\9
    :指示在搜索部分中找到的模式


  • 希望有用。

    您的假设是正确的,但我不理解您预期的输出或问题,因此请在您的帖子中添加输出示例,然后让我们知道。@ed morton,只想解释如何执行此操作以及它是如何工作的。出于这个原因,我已经花费了时间展示我对代码的想法,很抱歉发布得太快“我是新来的,我正在学习……”埃德·莫顿我知道有无数种方法可以做到这一点,而且很难解释所有的情况,我想如果我不理解这个句子以及它是如何运作的,我可以找到答案,让它做我想做的事。如果有人不得不这样做,这个问题可能会帮助他们走捷径。我没有找到答案他以前是在堆栈中回答的。@EdMorton As Always谢谢你。.你帮我只是告诉我如何回答这个问题。你必须使用awk吗?或者其他bash命令允许吗?哦,好吧,让我看看。@RavinderSingh13-我也喜欢这个。尽管我仍然对所有编辑一次添加几部分的内容有点困惑.从上一次编辑来看,他似乎希望在输出中保留可选字段分隔符。这是我的最佳猜测。
    :)
    是的,不幸的是,idk中还有一个完整的其他RE术语,但它在术语“字符类”中被广泛使用似乎同时引用了POSIX括号表达式和POSIX字符类
    $ awk -v nrs='1.4 3.2' -f tst.awk file
    Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh
    
    $ echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' | 
    perl -0777 -nE ' @a=qw(4 8 9);%k = map {$_,1} @a; s/(\w+)/$i++; $k{$i}==1 ? "\u\L$1":$1/ge; print'
    Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh Weeeeewrwr
    
    $ echo 'Aaaa Bbbb Cccc DDDD;Eeee Ffff;Gggg HHHH WEEEEEwrwr' | 
    perl -0777 -nE ' @a=qw(4 8 9);@k{@a}=undef; s/(\w+)/$i++; exists $k{$i} ? "\u\L$1":$1/ge ; print '
    Aaaa Bbbb Cccc Dddd;Eeee Ffff;Gggg Hhhh Weeeeewrwr
    
      echo 'Aaaa Bbbb Cccc dDDD;Eeee Ffff;Gggg HHHH' | sed -r 's/([a-zA-Z]{1})([a-zA-Z]+)/\U\1\L\2/g'