awk将变量视为regexp中的文字

awk将变量视为regexp中的文字,regex,linux,bash,variables,awk,Regex,Linux,Bash,Variables,Awk,我想将几个shell变量传递给awk命令,然后使用regex在字段上匹配它们。但是,我希望变量的内容在正则表达式中被视为文本。所有这些都是针对输入文件的每一行完成的 那么这个 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|fiel

我想将几个shell变量传递给awk命令,然后使用regex在字段上匹配它们。但是,我希望变量的内容在正则表达式中被视为文本。所有这些都是针对输入文件的每一行完成的

那么这个

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
但这些都不是

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}
我认为这不起作用,因为有开始和结束的锚,但我不知道如何修复这些锚,因此必须使用regex常量(/pattern/和前斜杠)

如果第二个示例中的锚可以固定,并且变量内容将被视为文本,那么这将是另一条路径


请注意-第一篇文章,让我知道要更改/改进/提供什么。

您需要在搜索词中转义
^
,因为它在正则表达式中有特殊意义

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 }

我不知道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
之间的任何内容都会自动转义/忽略任何元字符

也许应该澄清一下,这将全部包含在bash脚本中-因此,
读取
输入。如果bash内置的
printf
支持
%q
格式,请尝试
printf%q“$v”
,这将向
$v
添加转义符。