我想将几个shell变量传递给awk命令,然后使用正则表达式在字段上匹配它们。但是,我希望将变量的内容视为正则表达式中的文字。所有这些操作都是针对输入文件的每一行完成的。
所以这个
123^A
可以在任何这些
中找到123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3
但这些都不是
123^B|field2|field3
1234^A|field2|field3
123|field2|field3
123~000|field2|field3
不起作用的示例:
read inputfile?'Enter the input file: '
read tackedonvalue?'Enter the value to tack onto each input value: '
read searchfile?'Enter the search file: '
read fieldnum?'Enter the field number to search: '
read delim?'Enter the field delimiter: '
while read -r SEARCHTERM
do awk -F"${delim}" -v a="(^|~)${SEARCHTERM}${tackedonvalue}(~|$)" -v COL="${fieldnum}" '$COL ~ /a/' ${searchfile} >> output_file.txt
done < ${inputfile}
$inputfile
变量的一行$tackedonvalue
变量使此示例无法正常工作的原因是$tackedonvalue
变量中经常包含^
个字符,然后需要对正则表达式进行转义。 (不是在输入中手动转义的选项。)在该变量中可能还输入了其他特殊字符,这些特殊字符也需要转义,因此我不想在每个特殊字符上查找/替换对于每种情况。
我首先尝试过但无法正常工作的另一个示例(与以前相同的输入提示和while read
):
awk -F"${delim}" -v a="${SEARCHTERM}" -v b="${tackedonvalue}" -v COL="$fieldnum" '$COL ~ ("(^|~)" a b "(~|$)")' ${searchfile} >> output_file.txt
我认为由于开始和结束锚点,这是行不通的,但是我不知道如何解决这些问题,因此必须使用regex常量(/ pattern /带有正斜杠)。
如果可以在第二个示例中固定锚点,并且将变量内容视为文字,那么这将是另一条路线。
P.S。 -第一篇文章,让我知道要更改/改进/提供的内容。
答案 0 :(得分:1)
您需要对搜索词中的^
进行转义,因为它在正则表达式中具有特殊含义。
SEARCHTERM=${SEARCHTERM//^/\\^}
如果搜索词可能包含在正则表达式中具有特殊含义的其他字符,则需要全部替换。在awk本身中这样做会更容易:
awk -v -F"$delim" search="$SEARCHTERM" -v tacked="$tackedonvalue" -v col="$fieldnum" '
BEGIN {gsub(/[]*^$]/, "\\&", search); pattern = "(^|~)" search tacked "(~|$)" }
$col ~ pattern' "$searchfile"
顺便说一句,您不应该使用全部大写的shell变量。习惯上,这些名称是为环境变量保留的。
但是也许您根本不应该使用模式匹配。我认为您可以只拆分~
字符上的字段,然后遍历该数组测试是否有任何元素与搜索字符串匹配。
split($col, array, "~");
for (i in array) if (array[i] == (search tacked)) { print; break }
答案 1 :(得分:0)
我不了解awk,但这很容易用perl完成:
$ cat a.txt
123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3
123^B|field2|field3
1234^A|field2|field3
123|field2|field3
123~000|field2|field3
$ export PAT=123^A
$ export FIELDNUM=0
$ perl -F'\|' -le "print if \$F[${FIELDNUM}] =~ /(^|~)\Q${PAT}\E(~|$)/" a.txt
123^A|field2|field3
123^A~000^A|field2|field3
000^A~123^A|field2|field3
000^A~123^A~999^A|field2|field3
正则表达式中\Q
和\E
之间的任何字符都会自动转义/忽略任何元字符。