AWK意外的substr()行为

时间:2014-01-04 20:11:31

标签: awk

使用AWK我想处理这个文本:

J.Nawrocki & W.Complak

分为:

Nawrocki J. & Complak W.

我有:

{ for(i=1;i<=NF;++i){
if ($i ~ /[A-Z]\.[A-Z][a-z]*/)
    {
    len=length($i);
    name=substr($i,1,2);
    surname=substr($i,3,len);
    printf("%s %s",surname,name);
    }
else printf("%s",$i);
}
printf("\n");
}

但是我只得到

 W.rocki J.&Complak

(第一个标志是一个空格)。为什么是“W”覆盖行的开头?

4 个答案:

答案 0 :(得分:2)

您可以尝试以下脚本:

{ 
    for(i=1;i<=NF;++i){
        if ($i ~ /[A-Z]\.[A-Z][a-z]*/)
        {
            len=length($i)
            name=substr($i,1,2)
            surname=substr($i,3)
            $i= surname" "name
        }
    }
    print 
}

请注意:

  • printf围绕其参数不需要括号..
  • 提取字符串的其余部分时,
  • substr()不需要三个参数。
  • 除非在一行上有多个分号,否则不需要在语句后加分号。

<强>更新

如果您使用的是dos行结尾,则可以

  • RS='\r\n'
  • 首先使用dos2unix
  • 将文件转换为unix格式

答案 1 :(得分:1)

awk -F' & ' -v OFS=" & " '{for(i=1;i<=NF;i++){split($i,a,".");$i=a[2]"."a[1]}}7' 

你的例子:

kent$  echo 'J.Nawrocki & W.Complak'|awk -F' & ' -v OFS=" & " '{ for(i=1;i<=NF;i++){ split($i,a,".");$i=a[2]" "a[1]"."}}7' 
Nawrocki J. & Complak W.

答案 2 :(得分:1)

很高兴它原来是一个以行为结尾的东西(你的原版在mac上也适合我)。作为一项个人练习,我设计了一种sed方法,如果您发现它在其他情况下有用,请在下面进行。

您当前代码的逻辑没有考虑多个首字母的可能性,带介词的名称(例如A. von Humboldt)等等。对于它的价值,这是一个具有相同约束的sed方法:

echo "J.Nawrocki & W.Complak" | sed -E 's/([A-Z]\.)([A-Z][a-z]*)/\2 \1/g'

可以使用任意数量的首字母:

echo "J.A.Nawrocki & W.Complak" | sed -E 's/(([A-Z]\.)+)([A-Z][a-z]*)/\3 \1/g'

和一个带有可以有前置介词的姓氏(有或没有空格):

echo "J.A.Nawrocki & W.von Complak" | sed -E 's/(([A-Z]\.)+)([a-z]*[[:space:]]?[A-Z][a-z]*)/\3 \1/g'

答案 3 :(得分:0)

mawk'{sub(/J.Nawrocki&amp; W.Complak /,“Nawrocki J. \&amp; Complak W。”)} 1'文件
Nawrocki J.&amp; Complak W。