用Awk替换并保留FS到OFS

时间:2017-01-30 12:49:40

标签: awk fs

我有一个带有输入文本的文件(这不是原始文件,只是输入文本的示例),我想将所有2个字母的字符串替换为数字100。在这个文件中FS可以是:,|或" " (空格),我别无选择,只能将它们全部三个都视为FS,我想在输出中的原始位置(如输入文件中)保留这些字段分隔符

A:B C|D
AA:C EE G
BB|FF XX1 H
DD:MM:YY K

我试过了

awk  -F"[:| ]"  '{gsub(/[A-Z]{2}/,"100");print}'

但这似乎不起作用,请建议。

期望的输出:

A:B C|D
100:C 1000 G
100|100 1001 H
100:100:100 K

4 个答案:

答案 0 :(得分:3)

POSIX awk中没有保留与RS(POSIX)定义的字符串或FS定义的regexp匹配的字符串的功能。因为POSIX RS只是一个字符串,所以不需要这样的功能,并且对于每个FS匹配字符串来说这样做是不必要的低效,因为它很少需要。

使用GNU awk,其中RS可以是正则表达式,而不仅仅是字符串,您可以保留与正则表达式RS匹配的字符串,但是没有功能可以保留与FS匹配的值,这与POSIX没有相同的效率原因相同。 #39;做到了。相反,在GNU awk中,他们在split()中添加了第4个arg,因此如果需要,可以自己保留数组中与FS匹配的字符串(seps[]以下):

$ awk -v FS='[:| ]' '{
    split($0,flds,FS,seps)
    gsub(/[A-Z]{2}/,"100")
    for (i=1;i<=NF;i++) {
        printf "%s%s", $i, seps[i]
    }
    print ""
}' file
A:B C|D
100:C 100 G
100|100 1001 H
100:100:100 K

the GNU awk manual中查找split()以获取更多信息。

答案 1 :(得分:1)

在这种情况下

sed 's/[A-Z]\{2\}/100/g' YourFile
awk '{gsub(/[A-Z]{2}/, "100"); print}' YourFile

在这种情况下不需要字段分隔,将所有大写字母组都改为“100”,除非你在OP中指定其他约束(就像字符串中的其他元素一样,你需要指定什么是可能的,理想的,添加预期结果的样本为univoq)

现在你肯定还有更多的东西,所以这个代码肯定会失败,因为ABC:DEF改为100C:100F,这肯定不是预期的

在这种情况下

awk -F '[[:blank:]:|]+' '
   {
   split( $0, aS, /[^[:blank:]:|]+/)
   for( i=1;i<=NF;i++){
      if( $i ~ /^[A-Z][A-Z]$/) $i = "100"
      printf( "%s%s", $i, aS[i+1])
      }
   printf( "\n" )
   } ' YourFile

答案 2 :(得分:0)

试试这个sed one-liner:

kent$  sed -r 's/(^|[:| ])[A-Z][A-Z]([:| ]|$)/\1100\2/g' file  
A:B C|D
100:C 100 G
100|FF XX1 H
100:MM:100 K

注意:

这将搜索并替换模式:两个分隔符之间的两个[A-Z] 。如果这不是您想要的,请粘贴所需的输出。

答案 3 :(得分:0)

你的代码似乎与我的Gnu awk一样好用:

A:B C|D
100:C 100 G     # even the typo in this record got fixed.
100|100 1001 H
100:100:100 K

我想问题是正则表达式/[A-Z]{2}/应该写成/[A-Z][A-Z]/