匹配并打印与长字符串中的某个模式匹配的所有单词

Match and print all words matching some pattern in a long string

我的文本文件有以下几行(实际上更长):

U-what's-WORD|C U--PW|C U-you-NW|C U-what's--W-PW|C U-PROGRAM-GAZ|C
U-timothy-WORD|C U--PW|C U-green-NW|C U-timothy--W-PW|C

U-life-WORD|C U-odd-PW|C U--NW|C U-life-odd-W-PW|C
U-green-PW|C U-life-NW|C U-PROGRAM-GAZ|C U-odd-green-W-PW|C

U-green-xxxxk-DISJP-CS|C U-timothy-xxxxk-DISJP-CS|C U-PROGRAM-GAZ1|C U-PROGRAM-GAZ|C

我想打印所有只包含“GAZ”的单词。如果一行不包含任何这样的词,则打印空行。

我尝试使用 grep 进行搜索,但它匹配并打印了整行。我尝试在 sed 中使用带有边界的捕获组 (\b.P.\b) 并打印该组 \1 无济于事。

编辑 一种直接的方法(我还不想实现)是编写 python 脚本。该脚本将逐行运行:

  1. 使用空格分隔符对字符串进行标记
  2. 将每个标记与模式 P 匹配,如果匹配则打印它
  3. 如果整行都没有匹配,就打印空行

这将打印一行中与模式 P 匹配的任何单词。如果没有找到单词,则打印一个空行:

$ awk -v P=GAZ '{for (i=1;i<=NF;i++) if($i~P)printf "%s ",$i; print ""}' file
U-PROGRAM-GAZ|C 



U-PROGRAM-GAZ|C 

U-PROGRAM-GAZ1|C U-PROGRAM-GAZ|C 

工作原理

  • -v P=GAZ

    这定义了模式 PP可能是正则表达式。

  • for (i=1;i<=NF;i++) if ($i ~ P) printf "%s ",$i

    循环遍历行中的每个单词。如果该词匹配模式 PP 可能是正则表达式),则打印该词。

  • print ""

在每行的末尾,无论是否匹配,都会打印一个换行符。

我假设 "word" 是一个非空白序列。这里的关键是 grep 的 -o 选项,它只打印正则表达式匹配的内容,而不是整行。

while IFS= read -r line; do
    grep -oP '\S*GAZ\S*' <<< "$line" | tr '\n' ' '
    echo 
done < file
U-PROGRAM-GAZ|C 



U-PROGRAM-GAZ|C 

U-PROGRAM-GAZ1|C U-PROGRAM-GAZ|C 
sed 's/.*/ & /;s/ /  /g;s/GAZ/³/g;s/ [^ ³]\{1,\} / /g;s/³/GAZ/g;s/  */ /;s/.\(.*\).//' YourFile
  • 对于 posix sed(没有 不是这个组 可用的正则表达式)
  • 假设字符串中没有³(可以使用其他临时字符或添加转义序列,有点重)

原则:

  • 删除线上没有 GAZ 的组
  • 因为 GAZ 不能作为排除选择,将 GAZ 替换为 ³ 并排除 ³ 这是一个单一的 univoq char class 排除,放回 GAZ之后。
  • 调整字符串以便于选择(在开头和结尾添加一个 space,双 space)并在结尾重新格式化