grep后查找字符串

Finding a string after grep

我有这个文件:

a=1 b=2 1234j12342134h d="a v" id="y_123456" something else 
a=1 b=2 1234j123421341 d="a" something else 
a=1 b=2 1234j123421342 d="a D v id=" id="y_123458" something else 
a=1 b=2 1234j123421344 d="a  v" something else 
a=1 b=2 1234j123421346 d="a.a." id="y_123410" something else 

并且我只想检索包含 'id=' 的行,以及 id 和第 3 列的值。最终产品应该是

1234j12342134h id="y_123456" 
1234j123421342 id="y_123458"
1234j123421346 id="y_123410"

1234j12342134h "y_123456" 
1234j123421342 "y_123458"
1234j123421346 "y_123410"

甚至

1234j12342134h y_123456 
1234j123421342 y_123458
1234j123421346 y_123410

我在表达式的开头和结尾尝试了 grep -o,但它遗漏了第一个 ID 块。我尝试了 awk,但对于带有空格的列来说失败了。

我可以使用 Java,但随着日志文件变大,速度变慢了。

如何使用 bash 实用程序来完成?

仅使用 Unix shell,可能bash 实用程序 误认为是内置函数(对我而言),其 read 命令可以根据输入字段分隔符 IFS(默认为空白)将每一行拆分为您选择的字段变量。例如,只处理你在测试用例中的第一行,

$ echo a=1 b=2 1234j12342134h d="a v" id="y_123456" something else | \
  if read ign1 ign2 f3 ign4 ign5 f6 rest
    then echo $f3 $f6;
  fi
1234j12342134h id=y_123456
$

您可以从这里转到 cat 和一个 while 循环,read 处理所有行,并根据其结构处理每一行。 (请注意,在上面的方法中,您将丢失引号字符,因为它们由 shell 解释。)处理这些片段可能会变得相当复杂,需要更多的命令和条件。

因此,更好的选择包括使用 awk 或 Perl,以及根据您的 Java 解决方案改编的字符串处理逻辑。在任何解决方案中,在每一行的特定位置拆分输入似乎是一个很好的第一步,因为 grep 的单个包罗万象的正则表达式似乎相当棘手。

使用 GNU awk(对于 match() 的第三个参数):

$ gawk 'match([=10=],/id="[^" ]+"/,a){ print , a[0] }' file
1234j12342134h id="y_123456"
1234j123421342 id="y_123458"
1234j123421346 id="y_123410"

与其他 awks:

$ awk 'match([=11=],/id="[^" ]+"/){ print , substr([=11=],RSTART,RLENGTH) }' file
1234j12342134h id="y_123456"
1234j123421342 id="y_123458"
1234j123421346 id="y_123410"

或者如果你想去除一些 leading/trailing 字符,有两种方法:

$ gawk 'match([=12=],/id="([^" ]+)"/,a){ print , a[1] }' file
1234j12342134h y_123456
1234j123421342 y_123458
1234j123421346 y_123410

或:

$ awk 'match([=13=],/id="[^" ]+"/){ print , substr([=13=],RSTART+4,RLENGTH-5) }' file
1234j12342134h y_123456
1234j123421342 y_123458
1234j123421346 y_123410