【发布时间】:2014-11-25 15:20:26
【问题描述】:
我正在尝试使用 awk 做两件事。我想将一个列表分成三个单独的列表,并将每个列表的 1 或 2 列转换为正则表达式。当我将 awk 传递给自身时,即在列表中选择我的项目,然后使用 awk 进行替换,它会将 1 附加到列表项。
我认为我不需要将 awk 传递给自身,而是在一次调用 awk 时完成所有这些操作。
AH??0*,*,ARRAY RESISTIVITY,RESISTIVITY
AHD*,*,MEASURED DEPTH,REFERENCE
AI*,*,ACOUSTIC IMPEDANCE COMPRESSIONAL,GEOPHYSICAL SYNTHETICS
AI_AVG_HOR_SIG,*,ACOUSTIC IMPEDANCE,ACOUSTIC
*,FOO,BAR,BLEH
列表一将是类似于第 4 行的行,第一列中没有通配符,替换第 2 列中的通配符。
列表 2 将用于单独列表中的第 1,2 和 3 行,并且需要对第 1 列和第 2 列进行替换。
最后,我需要在单独的列表中为第 5 行做类似的事情。
我可以这样做。
第 4 行:awk -F \, '$1!~/([\*\?])/' file.txt
第 1-3 行:awk -F \, '$1~/([\*\?])/' file.txt
第 5 行:awk -F \, '$1~/^\*$/' file.txt
我的潜艇是 * => .* 和 ? => [0-9]。
当我尝试像 awk -F \, 'gsub(/\*/,".*",$2) $1!~/([\*\?])/' OFS=, file.txt 这样使用 gsub 时,列表返回时会出现意想不到的结果。关于堆栈操作,我觉得 awk 有一个基本的东西我不明白。
停下来!
【问题讨论】:
-
您需要将
gsub放在一个动作块中。{gsub(...)}。现在它是一种模式。所以它执行它的任务,然后告诉 awk 打印当前行。如果您只希望在$1~....模式匹配时使用该 gsub,那么您希望将 gsub 放入该模式的操作块中(并且您还需要添加print)。 -
这对我有用。我现在唯一的问题是这个
awk -F \, '$1~/[\*\?]/ && $1!~/^\*$/' {gsub(/\*/,".*",$1) ; gsub(/\?/,"[0-9]",$1) ; gsub(/\*/,".*",$2);print} OFS=, file.txt会导致错误。可能是因为我正在做两个正则表达式比较。不知道如何解决这个问题。 -
您过早地结束了 awk 脚本(单引号字符串)。单引号需要在最后的
;print}之后而不是$1!~/^\*$/之后。 -
感谢伊坦!我最终使用:
awk 'BEGIN{FS=","}{if($1~/[\*\?]/ && $1!~/^\*$/){ gsub(/\*/,".*",$1); gsub(/\?/,"[0-9]",$1); gsub(/\*/,".*",$2); print; } }' OFS=, file.txt -
您可以将测试提升到一个动作而不是使用
if (),但我不知道这在任何方面都很重要,但在风格上。我还会选择一种设置变量的方法,BEGIN或从命令行,但这只是样式。