我在 awk 正则表达式匹配方面遇到问题。我试图将特定列与正则表达式模式匹配(\"\.\"|0|1)
。此列只能包含值"."
或0
。1
但是我的正则表达式模式在 awk 中不匹配,而列中的数据是"."
。有什么想法吗??
代码
awk -F "$delimitter" -v n="$column" -v m="$pattern" 'NR!=1 && $n !~ "^" m "$" {
printf "%s:%s:%s\n", FILENAME, FNR, $n > "/dev/stderr"
count++
}
END {print count+0}' input.txt 2>> errors.log
答案1
如果您希望模式与任一"."
(包含引号)或 完全匹配,0
则1
需要模式为^("\."|[01])$
or^("[.]"|[01])$
或^("\."|0|1)$
等。
但是,当使用-v
将该模式传递给时,您会遇到在那里进行特殊处理awk
的问题(对于类似于 的情况也会发生同样的情况),因此您需要在此处转义反斜杠。awk
\
-F x
-v FS=x
最好使用ENVIRON
从 shell 传递任意字符串,因为awk
这样就不存在这个问题。
所以:
pattern='"\."|0|1'
PATTERN=$pattern DELIMITER=$delimiter awk -v n="$n" '
BEGIN {FS = ENVIRON["DELIMITER"]; m = ENVIRON["PATTERN"]}
$n ~ "^(" m ")$" {...}'
(仍然使用-v
forn
因为这些预计是数字,所以没有反斜杠)。
请注意上面的(
, )
。^x|y$
要么x
在开头,要么y
在结尾。
答案2
匹配文本时不要使用“模式”一词,因为它非常不明确。使用“字符串”或“正则表达式”,无论您指的是哪一个。看如何找到与模式匹配的文本了解更多信息。
听起来你正在解决这个错误,并使用正则表达式比较,其中哈希查找中的字符串比较会更清晰、更不脆弱且更高效。
valid='"."|0|1'
awk -F "$delimitter" -v n="$column" -v m="$valid" '
BEGIN {
split(m,tmp,"|")
for (i in tmp) {
valid[tmp[i]]
}
}
NR>1 && !($n in valid) {
printf "%s:%s:%s\n", FILENAME, FNR, $n > "/dev/stderr"
count++
}
END {print count+0}
' input.txt
如果任何 shell 变量可以包含转义序列(示例中的变量不包含转义序列),请参阅https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script除了-v
将它们的值传递给 awk 之外的其他方式,例如ENVIRON[]
或ARGV[]
。
答案3
尝试[.01]
作为你的模式。
这是一个仅匹配.
, 0
, 和 的括号表达式1
。
注意:在括号表达式之外,您必须转义.
as \.
(否则它将匹配任何字符),但在括号表达式内它将被视为文字.