我只是想找到一种方法来检查一个字符串值是否存在于一个csv列使用awk
命令。除了包含特殊字符(如(
或[
)的字符串外,它可以正常工作。
它适用于没有特殊字符的文本。然后当我尝试用特殊字符搜索文本时,它不起作用,所以我试图摆脱这些字符,但它也不起作用。
所以我得到了一个test.csv
文件,其中包含一行如下:
"hello","(hello)","this is a test (bye)","Alright"
然后如果我尝试搜索第一个字段,如:
text="hello"; awk -F '","' -v text="$text" '$1~text {print $4}' test.csv
它返回Alright"
,这很好。
然后如果我尝试搜索第二个字段,如:
text="(hello)"; awk -F '","' -v text="$text" '$2~text {print $4}' test.csv
它返回Alright"
,这也很好。
然后如果我尝试搜索第三个字段,如:
text="this is a test (bye)"; awk -F '","' -v text="$text" '$3~text {print $4}' test.csv
它什么也不返回。
如果我尝试转义特殊字符,比如:
text="this is a test \(bye\)"; awk -F '","' -v text="$text" '$3~text {print $4}' test.csv
它返回一条消息,如下所示:
awk: warning: the escape sequence '\(' is treated as a simple "("
awk: warning: the escape sequence '\)' is treated as a simple ")"
没有像以前那样的结果。
2条答案
按热度按时间9q78igpj1#
只关注不匹配的正则表达式问题。
~
操作符表示将操作的右侧作为正则表达式处理。当右边是一个字符串(或包含字符串的变量-如本例所示)时,字符串被转换为正则表达式(参见GNU awk - Using Dynamic Regexps)。在这种情况下:
比较(
$3~text
)转换为:在这里,括号被视为特殊的正则表达式字符,not 被视为文字括号,所以这实际上是相同的:
它与数据(包含文本括号)不匹配。
为了匹配字面括号,我们可以转义括号,例如:
但是OP发现,当处理包含字符串(即
text="this is a test \(bye\)"
)的(bash
)变量时,转义这些括号并不容易。另一种选择是将括号括起来,例如:
其中 * 可以 * 包含在变量中,即,以下确实有效:
下一个(更大的)问题是如何用必要的方括号对(
bash
)变量重新格式化;请记住,在正则表达式中还有其他具有特殊含义的字符(例如,.
、*
、[
和]
)。在这一点上,当试图弄清楚哪些字符需要在(
bash
)变量中“转义”时,它开始变得非常混乱。一种更简单的方法是查看处理 * 字符串 *(而不是 * 正则表达式 *)的不同比较方法。正如在评论中提到的,这就是
index()
函数派上用场的地方。index()
函数的第二个参数被处理为字符串(而不是正则表达式),因此无需担心某些字符(例如,(
和)
)被不同/特殊处理。如果没有找到第二个参数,index()
将返回0
,否则将返回一个整数,表示第二个参数的位置。[注意:awk
将0
视为false
,将其他任何数字视为true
]这意味着我们可以保留原来的(
bash
)变量赋值,而对awk
脚本做一个小的修改:这将返回:
**注意:**有关各种字符串函数的详细信息,请参阅GNU awk - String Functions;请注意哪些参数被视为 * 字符串 * 与 * 正则表达式 *
那么第二段代码是什么呢?
awk
将其视为:实际上是:
净结果是,这计算为true,因为它匹配文字字符串
hello
,并且(基本上)忽略数据中的文字括号。注意:
text="(hello)"
/$1~text
在这种情况下也会计算为true。tv6aics12#
对于
-F '","'
,第一个字段值是"hello
,而不是hello
或"hello"
。我认为,这就是为什么你认为你需要做regexp而不是字符串比较,但你发现这是错误的解决方案。使用-F ","
不仅会导致您当前的问题,而且它很脆弱,因为它会失败,因为它会像"head","foo"",""bar","tail"
这样的输入,其中中间字段"foo"",""bar"
包含嵌套的转义引号,引号之间有逗号。FPAT
使用GNU awk:你可以用任何awk**来做这件事,但你需要写更多的代码:
有关使用awk阅读CSV的更多信息,请参阅What's the most robust way to efficiently parse CSV using awk?。
如果你的
text
字符串可以包含反斜杠,那么请参阅How do I use shell variables in an awk script?,了解除了-v
(解释转义序列)之外的其他方法,在脚本之外为awk变量赋值。