如何使用`awk`以便我可以有条件地改变行中的一个或两个字段?

时间:2011-11-21 22:38:44

标签: awk

我有一个带有16个字段的制表符分隔文件。我可以使用awk有条件地改变一个或多个字段并打印整行作为输出吗?例如,根据第一个字段中的值,我想说一个特定的数字添加到字段4,依此类推。但作为输出我必须打印整行。如果是的话,我想知道如何。

3 个答案:

答案 0 :(得分:6)

是的,这是一种方法:

awk '$1 == "ALTER" { $5=$5+5 } 1'

使用etuardu的示例文件,会产生

ALTER xx yy zz 15 10
NOALT aa bb cc 20 20
ALTER 11 22 33 35 30

这是它的工作原理。有两种情况,表示为awk模式和操作。在第一个模式中,模式是对第一个字段的测试,以查看它是否等于"ALTER",如果模式评估为true,则调用修改第五个字段的操作。第二种模式是最终1;它始终是真的,因此执行隐式print动作。

使用此解决方案的一个怪癖:输入中读取的字段分隔符不必是输出中的字段分隔符。使用上面的简单形式,输入中的字段分隔符被视为空格,而单个空格被写入输出;如果不是您想要的,请将FSOFS设置为特定值。但是,只有更改字段的行才会有新的字段分隔符,因此像'$ 1 = $ 1'这样的空操作将强制重建所有记录(这是更改字段分隔符的一种方便方法,仅使用{{1 }})。

答案 1 :(得分:1)

是。这是一个使用示例(可能不是最聪明的):

etuardu@subranu:~$ cat sample.txt 
ALTER xx yy zz 10 10
NOALT aa bb cc 20 20
ALTER 11 22 33 30 30
etuardu@subranu:~$ awk '{ if ($1=="ALTER") print $1,$2,$3,$4,$5+1,$6-1; else print $0 }' sample.txt 
ALTER xx yy zz 11 9
NOALT aa bb cc 20 20
ALTER 11 22 33 31 29

请参阅man awk或一些在线教程(有很多内容)以获取更多信息。

答案 2 :(得分:1)

这个(来自@etuardu的文件样本) -

awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' input_file | sed '/^$/d'
  • 使用if语句检查要更改的特定行。
  • 如果找到预期的字段然后进行更改,例如。 $ 5 = $ 5 + 1 ... 等等。
  • 通过根据字段数重复循环来运行for循环。
  • 打印包含更新字段的字段。
  • 如果未找到预期字段,请运行else循环。
  • sed将删除因新行而创建的所有空白行。

示例:

[jaypal~/Temp]$ cat text8
NOALT aa bb cc 20 20
ALTER xx yy zz 10 10
ALTER xx yy zz 10 10
NOALT aa bb cc 20 20
ALTER 11 22 33 30 30

[jaypal~/Temp]$ awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' text8 | sed '/^$/d'
NOALT aa bb cc 20 20
ALTER xx yy zz 11 10 
ALTER xx yy zz 11 10 
NOALT aa bb cc 20 20
ALTER 11 22 33 31 30