0

我已经尝试了几十种正则表达式的排列来解决这个问题,但我没有遇到任何运气。

我需要遍历数十个文件,在“the/a/an”和可能数字为 1-4 的数字之间提取特定短语,忽略标点符号,例如 {}()[]。

例子

敏捷的棕色狐狸 {15} 以某种方式跳过懒狗 [20] 4,这绝对不适合所有观众 (0012)。

应该返回:

快速棕色狐狸 15

懒狗 20

某种方式 4

观众0012

消除标点符号不是问题:sed 's/[][{}()]//g'

有什么建议吗?

4

4 回答 4

1

在 GNU awk 中,您可以将输入拆分为以数字结尾的记录,这些记录可选地用标点符号包围:

$ cat file
The quick brown fox {15} jumps over the lazy dog [20] in a certain way 4 that is definitely not appropriate for all of the viewers (0012).


$ gawk -v RS='[[:punct:]]*[[:digit:]]+[[:punct:]]*' 'RT{print $0 RT}' file
The quick brown fox {15}
 jumps over the lazy dog [20]
 in a certain way 4
 that is definitely not appropriate for all of the viewers (0012).

然后您需要做的就是打印您想要的记录部分和记录终止符:

$ gawk -v RS='[[:punct:]]*[[:digit:]]+[[:punct:]]*' 'RT{print gensub(/.*\y(the|a|an)\y/,"\\1","") gensub(/[[:punct:]]/,"","g",RT)}' file
The quick brown fox 15
the lazy dog 20
a certain way 4
the viewers 0012

我刚刚注意到,在您的示例中,您将输出转换为全部小写。只需$0=tolower($0)在 print 之前添加一个 in 即可(也解决了the|a|an比较不区分大小写的问题):

$ gawk -v RS='[[:punct:]]*[[:digit:]]+[[:punct:]]*' 'RT{$0=tolower($0); print gensub(/.*\y(the|a|an)\y/,"\\1","") gensub(/[[:punct:]]/,"","g",RT)}' file
于 2013-04-02T00:39:00.250 回答
1

纯 Bash 和使用正则表达式的练习:

while read line ; do
  line=" $line"                                 # add leading space as word boundary

  while [ -n "$line" ] ; do
    [[ "$line" =~ [[:space:]]((an|a|the|An|A|The)([[:space:]]+[^[:digit:]]+)([[:digit:]]{1,4}))(.+$) ]]

    match="${BASH_REMATCH[2]}${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
    match=${match//[()\[\]\{\}]/}               # remove parentheses
    [ -n "$match" ] && echo "'$match'"          # print if not empty

    line="${BASH_REMATCH[5]}"                   # the postmatch
  done
done < "$infile"

输出:

'The quick brown fox 15'
'the lazy dog 20'
'a certain way 4'
'the viewers 0012'
于 2013-04-02T08:50:16.473 回答
0
grep -ioP "(a|an|the).*?\d{1,4}" files

-o仅打印匹配的文本,并且每个匹配项都在其自己的行上。 -P用于不情愿的量词,也使正则表达式自动扩展。您当然可以sed按照上面的建议将此输出通过管道传输到。

于 2013-04-01T23:10:12.023 回答
0

这可能对您有用(GNU sed):

sed -r '/\b(the|an|a)\b/I!d;s//\n&/;s/[^\n]*\n//;s/\{([0-9]{1,4})\}|\(([0-9]{1,4})\)|\[([0-9]{1,4})\]|\b([0-9]{1,4})\b/\1\2\3\4\n/;P;D' file
于 2013-04-02T15:16:15.907 回答