Shell 提取匹配部分模式的完整单词

Shell 提取匹配部分模式的完整单词

我需要从 shell 脚本中的一行中提取一个单词,我见过类似的例子,但没有一个起作用。

举个例句

word1 word2 word3/pattern/word4.word5 word6

鉴于pattern它应该返回,word3/pattern/word4.word5两边都没有空格。

此外,它应该限制该行不能以某些字符开始,#

我设法找到一个 grep 命令来隔离该行

grep "^[^#].*pattern" $FILE

将返回所有不以 开头#且不包含 的行pattern。那么我怎样才能从这一行中提取这个词呢?

编辑:使用ubuntu 20.04

另外,关于这个句子,这个例子或多或少与它应该是什么样子的有关。该模式每行最多出现一次,并通过空格与其他单词分隔开。给定一行,我想返回包含模式的单词,左右移动所有内容,直到遇到空格(不包括空格)。

答案1

只要模式不匹配任何空格,就grep -o '[^[:space:]]*pattern[^[:space:]]*'应该这样做。 ([^[:space:]]*匹配任意数量的非空白字符。)

正则表达式引擎通常从最左边的位置开始查找匹配,并且匹配是贪婪的,这意味着它们尽可能匹配字符串的一部分。因此,模式两侧的所有非空白都应该在这里被拾取。

要忽略以井号开头的行,您只需通过管道即可grep -v "^#"

所以例如如果hello.txt包含

# my pattern
word1 word2 word3/pattern/word4.word5 word6

然后:

% < hello.txt grep -v "^#" | grep -o '[^[:space:]]*pattern[^[:space:]]*'
word3/pattern/word4.word5

答案2

另一种 GNUgrep方法:

grep -oP '^[^#].*\K\S*pattern\S*" "$file"

-o标志grep仅返回该行的匹配部分,并且-P启用 Perl 兼容正则表达式 (PCRE),这让我们-K“忘记到目前为止匹配的所有内容”。这允许我们使用^[^#]“匹配除#行开头的 a 之外的任何字符”,但不包括结果中从开头开始的所有字符。 PCRE 还\S为我们提供了“非空白”。

总而言之,这将匹配不以 a 开头#且包含 的行,pattern然后将打印包含该模式的最长的非空白字符串。

请注意,如果在同一行上多次出现pattern,则由于.*之前的 ,这将返回最右侧的匹配项\K。要返回最左边的匹配项,请使用:

grep -oP '^[^#].*?\K\S*pattern\S*' file

答案3

GNU grep:

grep -oP '^(?<!#).*?\K(\w+[/\.])+\w+' file
word3/pattern/word4.word5

正则表达式匹配如下:

节点 解释
^ 字符串的开头
(?<! 向后看看看是否有:
# #
) 后视结束
.*? 除 \n 之外的任何字符(0 次或多次(匹配尽可能少的数量))
\K 重置比赛的开始(什么是Kept)作为使用后视断言的更短替代方案:环顾四周正则表达式中对 K 的支持
( 分组并捕​​获到 \1(1 次或多次(匹配尽可能多的数量)):
\w+ 单词字符(az、AZ、0-9、_)(1 次或多次(匹配尽可能多的数量))
[/\.] 任何字符:“/”、“.”
)+ \1 的结尾(注意:因为您在此捕获上使用量词,所以只有捕获模式的最后一个重复才会存储在 \1 中)
\w+ 单词字符(az、AZ、0-9、_)(1 次或多次(匹配尽可能多的数量))

相关内容