【问题标题】:Match and print all words matching some pattern in a long string匹配并打印与长字符串中的某个模式匹配的所有单词
【发布时间】:2015-03-12 03:09:06
【问题描述】:

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

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的所有单词?
  • @hwnd,是的,我想打印所有匹配 P 模式的单词。应该删除所有其他单词(如果从这个角度来看)
  • @hwnd 它只匹配并打印 P。此外,没有匹配 P 的单词的行不会打印为空行。
  • 在 grep 中使用 -o 参数仅打印匹配项而不是整行。
  • @AvinashRaj 我将 -o 参数与 grep 一起使用。它只打印 P,而不是整个单词。 P 是我用来匹配我要打印的单词的子字符串。

标签: regex sed grep


【解决方案1】:

这将打印一行中与模式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&lt;=NF;i++) if ($i ~ P) printf "%s ",$i

    这会遍历该行中的每个单词。如果该单词与模式P 匹配(P 可能是正则表达式),则打印该单词。

  • print ""

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

【讨论】:

  • 谢谢!几乎是我想要达到的目标!唯一要做的更改:如果同一行中有多个匹配项,只需在一行中一个接一个地打印匹配的单词(用空格分隔)。
  • @xeon 这实际上更简单。针对多个匹配项的同一行打印更新了答案。
  • printf 周围不需要{},因为它只有一个命令:awk -v P=GAZ '{for (i=1;i&lt;=NF;i++) if($i~P)printf "%s ",$i;print ""}'
【解决方案2】:

我假设“单词”是一个非空白序列。这里的关键是 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 

【讨论】:

  • 其实不需要-P:grep -o '[^[:blank:]]*GAZ[^[:blank:]]*'
【解决方案3】:
sed 's/.*/ & /;s/ /  /g;s/GAZ/³/g;s/ [^ ³]\{1,\} / /g;s/³/GAZ/g;s/  */ /;s/.\(.*\)./\1/' YourFile
  • 对于 posix sed(没有 not this group 正则表达式可用)
  • 假设字符串中没有³(可以使用其他临时字符或添加转义序列,有点重)

原理:

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

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 2016-10-23
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多