使用awk在txt文件中查找特殊字符

使用awk在txt文件中查找特殊字符,awk,Awk,我需要用许多不同的特殊字符和值扫描一个文件。 给定一组特殊字符-我需要在其旁边提供值: 547 %$ 236 \" 4523 &* 8876 (* 8756 "/ ... 我正在对gsub使用awk命令,以便按原样查找序列 awk -v st="$match_string" 'BEGIN {gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)} match($0,st) {print;exit}' file.txt 这个命

我需要用许多不同的特殊字符和值扫描一个文件。 给定一组特殊字符-我需要在其旁边提供值:

547 %$ 
236 \"
4523 &* 
8876 (*
8756 "/
...
我正在对gsub使用awk命令,以便按原样查找序列

awk -v st="$match_string" 'BEGIN {gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)} match($0,st) {print;exit}' file.txt
这个命令非常有效

> (*
>> 8876 (*
但是,我在使用命令定位\“序列时遇到问题 我试图向gsub添加不同的字符串来表示序列:

|\\|
|\\\\|
|\\\\"|
...
但结果总是:

> \"
>> 8756 "/
而我想要的结果是:

> \"
>> 236 \"
似乎gsub不起作用,而\“被解释为” 有什么想法吗

下面是要运行的简短脚本- -它应该在first_num中找到附加到值的符号 -接下来,它应该打印文件中与找到的符号相关的第一个值

first_num=$1
echo "looking for : $first_num"
sym_to_check=$(awk -v s="$first_num"  '$0~s {if ($0~s)print $2}' temp.txt)
echo "symbol - $sym_to_check"
first_val=$(awk -v s="$sym_to_check" 'BEGIN {gsub(/(\[|\]|\-|\$|\^|\*|\:|\+|\"|\(|\))/,"\\\\&",s)} $0~s {if ($0~s)print; if ($0~s)exit}' temp.txt)
echo "first val- $first_val"
假设txt文件为:

547 %$ 
111 [*
222 ()
5655 (*
454 )"
35 #!
743 \"
657 #!
236 \"
4523 &* 
8876 (*
456 \"
8756 "/
第一次跑步很好:

> bash temp1.sh 8876
    looking for : 8876
    symbol - (*
    first val- 5655 (*
脚本将查找附加到的第一个值(* 但下一次跑步很糟糕:

> bash temp1.sh 236
looking for : 236
symbol - \"
first val- 454 )"
符号是正确的-查找\“但在搜索附加到它的第一个值时,它会查找带有的第一个符号”
这将给出值454)“而不是所需的743\”

使用
-v st=“$match\u string”
初始化awk变量的方式是通过设计扩展转义序列(例如,
“$match\u string”中的
\t
将成为
st
中的文本选项卡字符)您正在使用一个regexp操作符,
match()
,但试图转义regexp元字符,使其看起来像是在进行字符串而不是regexp匹配,然后您在整行上进行部分匹配(例如,
$0~85
将匹配
1853
),而不是在特定字段上进行完全匹配(
$1==85

下面是如何在不解释转义序列的情况下从shell初始化awk变量,然后在特定字段中将它们作为完全匹配的文本字符串或数字进行测试,而不是在整行中部分匹配regexp:

$ match_string='\"'

$ st="$match_string" awk 'BEGIN{st=ENVIRON["st"]} $2==st{print; exit}' file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $2==st{print; exit}' "$match_string" file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $1==st{print; exit}' '743' file
743 \"
并非所有AWK都支持
ENVIRON[]
,因此第一种方法不适用于所有AWK,但第二种方法适用

有关如何从shell中设置awk变量的信息,请参见,当您想要进行文字字符串比较时,通常只使用字符串运算符(如
==
index()
)比使用regexp运算符(如
~
match()更简单
并尝试转义所有的regexp元字符,使它们看起来像字符串一样

但是,如果您确实希望转义所有regexp元字符,那么执行此操作的语法将是:

gsub(/[^^]/,"[&]",st); gsub(/\^/,"\\^",st)
而不是你问题中代码中的内容:

gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)

有关这是正确语法的解释,请参阅。

使用
-v st=“$match\u string”
初始化awk变量的方法是通过设计扩展转义序列(例如,
“$match\u string”中的
\t
将成为
st
中的文本选项卡字符)您正在使用一个regexp操作符,
match()
,但试图转义regexp元字符,使其看起来像是在进行字符串而不是regexp匹配,然后您在整行上进行部分匹配(例如,
$0~85
将匹配
1853
),而不是在特定字段上进行完全匹配(
$1==85

下面是如何在不解释转义序列的情况下从shell初始化awk变量,然后在特定字段中将它们作为完全匹配的文本字符串或数字进行测试,而不是在整行中部分匹配regexp:

$ match_string='\"'

$ st="$match_string" awk 'BEGIN{st=ENVIRON["st"]} $2==st{print; exit}' file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $2==st{print; exit}' "$match_string" file
743 \"

$ awk 'BEGIN{st=ARGV[1]; ARGV[1]=""} $1==st{print; exit}' '743' file
743 \"
并非所有AWK都支持
ENVIRON[]
,因此第一种方法不适用于所有AWK,但第二种方法适用

有关如何从shell中设置awk变量的信息,请参见,当您想要进行文字字符串比较时,通常只使用字符串运算符(如
==
index()
)比使用regexp运算符(如
~
match()更简单
并尝试转义所有的regexp元字符,使它们看起来像字符串一样

但是,如果您确实希望转义所有regexp元字符,那么执行此操作的语法将是:

gsub(/[^^]/,"[&]",st); gsub(/\^/,"\\^",st)
而不是你问题中代码中的内容:

gsub(/(\[|\]|\-|\$|\*|\:|\+|\"|\(|\))/,"\\\\&", st)

请参阅,以了解为什么这是正确语法的解释。

哪些输入有效,哪些无效?请提供您正在测试的输入和预期的输出,包括问题中的a,如\“不起作用-它们被翻译为“好的,我们知道了,提供一个我们可以轻松复制粘贴的示例,并解决您目前尚未接受任何问题的答案的问题。请阅读。哪些输入有效,哪些无效?提供您正在测试的输入和预期的输出,包括问题序列中的a,如\“不起作用-它们被翻译为”好的,我们知道了,提供一个我们可以轻松复制粘贴的示例,并处理您目前尚未接受任何问题的答案。请阅读。谢谢-st=“$match_string”awk”BEGIN{st=ENVIRON[“st”]}$2==st{print;exit}文件解决方案非常有效!!谢谢-st=“$match_string”awk”BEGIN{st=ENVIRON[“st”]}$2==st{print;exit}文件解决方案非常有效!!