使用unix命令打印匹配的模式

时间:2012-02-02 21:09:27

标签: regex unix command-line sed grep

一位同事来找我,我认为这个问题很简单,但事实证明是挑战性的。挑战在于:给定输入字符串,可以使用哪些Unix命令打印字符串中的任何匹配模式?

假设我们有以下输入字符串。

12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606

目标是打印出字符串中的任何5位或6位数字,但不打印任何4位或7位数字。

我们首先想到像这样使用sed:

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
  sed 's/.*[^0-9]\{1\}\([0-9]\{5,6\}\).*/\1/g'

但是,此命令仅打印出任何匹配模式的最后一次出现。

我们最终想出了使用sed和grep -Eo的组合。

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
  sed 's/^/ /' | sed 's/$/ /' | grep -Eo '[[:space:]]+[0-9]{5,6}[[:space:]]+' |
  sed 's/ $//' | sed 's/^ //'

它有效,但看起来有点笨拙。还有更好的方法吗?

6 个答案:

答案 0 :(得分:3)

GNU grep至少支持-o,我认为它也在POSIX版本中。

  

-o, - 仅匹配                 仅显示与PATTERN匹配的匹配行的一部分。

答案 1 :(得分:2)

trgrep怎么样?

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
  tr ' ' '\n' |
  grep '^[[:digit:]]\{5,6\}$'

或者正如dmckee建议的那样,您可以使用-o标记来跳过tr阶段(如果您的grep版本具有此标记):

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
  grep -o '\<[[:digit:]]\{5,6\}\>'

答案 2 :(得分:0)

在linux box上工作

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606"|egrep -o 's|[[:digit:]]{5,6} |p'

答案 3 :(得分:0)

如果您愿意,您实际上只能使用Bash内置功能执行此操作,而不使用trsedgrep等外部实用程序:

INPUT='12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606'
( set -f
  for word in $INPUT ; do
    if [[ $word =~ ^[0-9]{5,6}$ ]] ; then
      echo $word
    fi
  done
)

set -f是禁用文件名扩展,以便我们可以将$INPUT拆分为其组成单词,而不必担心它可能包含*或会扩展的内容文件名列表。( ... )包含set -f的效果,因此我们不必担心周围的上下文是否真的要禁用文件名扩展。)

答案 4 :(得分:0)

这可能对您有用:

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
sed 's/\<[0-9]\{,4\}\>//g;s/\<[0-9]\{7,\}\>//g;s/[^0-9]\+/ /g'
12345 789012 60606

或者:

echo "12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606" |
sed 'H;g;:a;s/\n\([0-9]\{5,6\}\)\> */\1 \n/;ta;s/\n[^ ]* /\n/;ta;s/..$//'
12345 789012 60606

答案 5 :(得分:0)

这会过滤每一行,只打印5或6位数字,但将其保留在一行

 perl -ne 'print join(" ",grep /\b[0-9]{5,6}\b/, split)."\n";'

如果输入

12345 4444 abc 789012 xyz 1234567 def 987654321 qrz 60606
hello
66666

输出

12345 789012 60606

66666