所以我想匹配文件上的字符串/或单词,但是没有使用任何外部工具(grep
等sed
),仅使用纯 bash...
本质上我想要相当于:
grep "string" file
或者
grep -w "string" file
在纯粹的bash中。
PS:我只关心匹配文件上的精确字符串(带或不带换行符),因此不需要完整的正则表达式支持(其他外部工具可能支持)。
答案1
你能行的。但这是一个非常非常糟糕的主意。它会比以下慢得多(慢几个数量级)grep
由于它依赖于特定 shell (Bash) 的功能,因此
这将打印出与作为第一个参数给出的正则表达式模式匹配的行,类似于grep pattern
:
#!/bin/bash -
regexp="$1"
ret=1
while IFS= read -r line || [ -n "$line" ]; do
if [[ $line =~ $regexp ]]; then
printf '%s\n' "$line"
ret=0
fi
done
exit "$ret"
将其另存为foo.bash
并像这样运行:
foo.bash pattern < inputFile
或者使用标准sh
语法,寻找固定字符串而不是正则表达式:
#!/bin/sh -
string="$1"
ret=1
while IFS= read -r line || [ -n "$line" ]; do
case $line in
(*"$string"*)
printf '%s\n' "$string"
ret=0
esac
done
exit "$ret"
(将 替换printf
为exit 0
以获得类似于grep -q
。)
为了让您了解它有多慢,我创建了一个只有 10001 行的文件,前 5000 行是foo
,然后是单个行bar
,然后是另一个 5000 行foo
:
perl -e 'print "foo\n" x 5000; print "bar\n"; print "foo\n" x 5000;' > file
grep
现在,比较上面脚本的时间:
$ time grep bar < file
bar
real 0m0.002s
user 0m0.002s
sys 0m0.000s
$ time ./foo.bash bar < file
bar
real 0m0.116s
user 0m0.101s
sys 0m0.016s
正如您所看到的,即使文件很小,差异也很明显。如果我们尝试使用更实质性的脚本,脚本轮流运行的时间几乎难以忍受:
$ perl -e 'print "foo\n" x 500000; print "bar\n"; print "foo\n" x 500000;' > file
$ time grep bar < file
bar
real 0m0.004s
user 0m0.000s
sys 0m0.004s
$ time ./foo.bash bar < file
bar
real 0m11.306s
user 0m10.117s
sys 0m1.188s
然而,这部分是因为 Bash 很慢。标准 sh 版本使用 Dash 运行得更快一些:
$ time dash foo2.sh bar < file
bar
real 0m3.467s
user 0m2.113s
sys 0m1.353s
不过,还是有差距的三个数量级。脚本需要几秒钟的时间,而不是近乎即时的grep
.这仍然是一个只有 100 万行、大小约为 4MB 的文件。我希望你能看到问题所在...