如何通过 awk 中的正则表达式匹配 space 或 \s
How to match space or \s via regex in awk
我正在尝试匹配以下模式,但最终没有匹配到。不确定我错过了什么。
这是示例文件。
There was a farmer, who had a dog
and Bingo : nameo
Bingo: nameio
我正在使用以下内容来匹配 "Bingo\s*:\s*"
之后的字符串
awk '{for(i=1; i<=NF; i++) if($i~/Bingo[ : ]*/) print $(i+1)}' sample.log
在第一场比赛后期待字符串“nameo”,但我得到“:”,第二场比赛很好,我得到“nameio”。
有人可以帮我解释一下为什么 space 没有被匹配吗?
[ : ]
(在您的正则表达式中)是一个 class 匹配单个 space 或冒号的字符。默认情况下,awk 字段在白色 space 上拆分,因此 Bingo :
是两个字段,而不是一个。默认情况下,字段永远不会包含白色 space.
我可能会将 :
添加到默认字段分隔符正则表达式中:
awk -v FS='[[:space:]:]+' '{
for (i=1; i<=NF; i++) {
if ($i == "Bingo") {
print $(i+1)
}
}
}'
虽然这确实将 foo:bar
之类的字符串拆分为两个字段。如果这有问题,可能是这样的:
awk '
{
for (i=1; i<=NF; i++) {
if ($i == "Bingo" && $(i+1) = ":") {
print $(i+2)
}
}
}'
在回答你的标题时,\s
是无效的 awk。除了原始 space (
),还有:
[[:space:]]
匹配任何白色 space 字符(space、制表符、换行、回车 return、换页、垂直制表符)
[[:blank:]]
匹配 space 或制表符
[ : ]*
模式部分等于 [: ]*
并表示 括号表达式 匹配零个或多个(尽可能多,由于 *
) 冒号或文字空格。在您的情况下,空格用作字段分隔符,因此不是字段值的一部分,因此您不能将逻辑与默认字段分隔符一起使用。
解决问题的方法有很多,这里介绍三种:
awk 'match([=10=],/Bingo : .*/){print substr([=10=],RSTART+8,RLENGTH)}' file
sed -n 's/^.*Bingo : \(.*\)//p' file
grep -oP 'Bingo : \K.+' file
awk 'match([=15=],/Bingo : .*/){print substr([=15=],RSTART+8,RLENGTH)}' file
命令使用awk
查找带有Bingo :
及其后任意文本的记录(行),匹配该子串,返回以匹配起始位置+开头的子串8(Bingo :
文本的长度)。
sed -n 's/^.*Bingo : \(.*\)//p'
命令用 -n
选项抑制默认行输出,然后用 Bingo :
找到一行,将此子字符串之后的任何文本捕获到第 1 组,将整行替换为这个值,只打印这个替换结果。
GNU grep
grep -oP 'Bingo : \K.+'
命令匹配(使用 PCRE 正则表达式引擎,参见 -P
选项)并输出(使用 -o
选项)一个或多个字符Bingo :
文本(\K
使正则表达式引擎“忘记”到目前为止匹配的文本)。
参见 online demo:
#!/bin/bash
s='There was a farmer, who had a dog
and Bingo : nameo
Bingo: nameio'
awk 'match([=11=],/Bingo : .*/){print substr([=11=],RSTART+8,RLENGTH)}' <<< "$s"
sed -n 's/^.*Bingo : \(.*\)//p' <<< "$s"
grep -oP 'Bingo : \K.+' <<< "$s"
每个命令后输出 nameo
。
我正在尝试匹配以下模式,但最终没有匹配到。不确定我错过了什么。
这是示例文件。
There was a farmer, who had a dog
and Bingo : nameo
Bingo: nameio
我正在使用以下内容来匹配 "Bingo\s*:\s*"
之后的字符串awk '{for(i=1; i<=NF; i++) if($i~/Bingo[ : ]*/) print $(i+1)}' sample.log
在第一场比赛后期待字符串“nameo”,但我得到“:”,第二场比赛很好,我得到“nameio”。
有人可以帮我解释一下为什么 space 没有被匹配吗?
[ : ]
(在您的正则表达式中)是一个 class 匹配单个 space 或冒号的字符。默认情况下,awk 字段在白色 space 上拆分,因此 Bingo :
是两个字段,而不是一个。默认情况下,字段永远不会包含白色 space.
我可能会将 :
添加到默认字段分隔符正则表达式中:
awk -v FS='[[:space:]:]+' '{
for (i=1; i<=NF; i++) {
if ($i == "Bingo") {
print $(i+1)
}
}
}'
虽然这确实将 foo:bar
之类的字符串拆分为两个字段。如果这有问题,可能是这样的:
awk '
{
for (i=1; i<=NF; i++) {
if ($i == "Bingo" && $(i+1) = ":") {
print $(i+2)
}
}
}'
在回答你的标题时,\s
是无效的 awk。除了原始 space (
),还有:
[[:space:]]
匹配任何白色 space 字符(space、制表符、换行、回车 return、换页、垂直制表符)[[:blank:]]
匹配 space 或制表符
[ : ]*
模式部分等于 [: ]*
并表示 括号表达式 匹配零个或多个(尽可能多,由于 *
) 冒号或文字空格。在您的情况下,空格用作字段分隔符,因此不是字段值的一部分,因此您不能将逻辑与默认字段分隔符一起使用。
解决问题的方法有很多,这里介绍三种:
awk 'match([=10=],/Bingo : .*/){print substr([=10=],RSTART+8,RLENGTH)}' file
sed -n 's/^.*Bingo : \(.*\)//p' file
grep -oP 'Bingo : \K.+' file
awk 'match([=15=],/Bingo : .*/){print substr([=15=],RSTART+8,RLENGTH)}' file
命令使用awk
查找带有Bingo :
及其后任意文本的记录(行),匹配该子串,返回以匹配起始位置+开头的子串8(Bingo :
文本的长度)。
sed -n 's/^.*Bingo : \(.*\)//p'
命令用 -n
选项抑制默认行输出,然后用 Bingo :
找到一行,将此子字符串之后的任何文本捕获到第 1 组,将整行替换为这个值,只打印这个替换结果。
GNU grep
grep -oP 'Bingo : \K.+'
命令匹配(使用 PCRE 正则表达式引擎,参见 -P
选项)并输出(使用 -o
选项)一个或多个字符Bingo :
文本(\K
使正则表达式引擎“忘记”到目前为止匹配的文本)。
参见 online demo:
#!/bin/bash
s='There was a farmer, who had a dog
and Bingo : nameo
Bingo: nameio'
awk 'match([=11=],/Bingo : .*/){print substr([=11=],RSTART+8,RLENGTH)}' <<< "$s"
sed -n 's/^.*Bingo : \(.*\)//p' <<< "$s"
grep -oP 'Bingo : \K.+' <<< "$s"
每个命令后输出 nameo
。