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
我有这个文件:
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