DEK*_*KER 5 grep bash sed awk text-processing
我需要找出给定搜索字符串第一次出现的行号,该搜索字符串应该位于文本文件中行的开头,并将其存储在我的 bash 脚本中的变量中。例如我想找到第一次出现的“c”:
abc
bde
cddefefef // this is the line that I need its line number
Casdasd // C here is capital, I dont need it
azczxczxc
b223r23r2fe
Cssdfsdfsdf
dccccdcdcCCDcdccCCC
eCCCCCC
Run Code Online (Sandbox Code Playgroud)
我想出了这个,但正如你所见,存在很大的问题
trimLineNum=$(cat "${varFileLog}" | grep -m1 -n "c")
echo "c is at line #"${trimLineNum}
Run Code Online (Sandbox Code Playgroud)
输出将是:
c is at line #1:abc
Run Code Online (Sandbox Code Playgroud)
问题:
我应该改变什么来解决这些问题?
使用 POSIX sed
,您可以使用选项抑制正常输出,然后对于以(pattern )-n
开头的行,使用和uit打印行号:c
^c
=
q
sed -n '/^c/{=;q;}'
Run Code Online (Sandbox Code Playgroud)
使用 GNU sed
,您可以使用Q
命令退出而不输出并简化为
sed '/^c/!d;=;Q'
Run Code Online (Sandbox Code Playgroud)
存在多种解决方案
awk '/^c/ { print NR; exit}' "${varFileLog}"
Run Code Online (Sandbox Code Playgroud)
/^c/
: 匹配以以下开头的行c
print NR
:打印记录(行)号exit
: 不继续处理如我所愿awk
,这是我的首选解决方案
grep -n '^c' "${varFileLog}" | head -n1 | sed 's/:.*//'
Run Code Online (Sandbox Code Playgroud)
'^c'
: 匹配以以下开头的行c
head -1
: 只显示 grep 结果的第一行sed 's/:.*//'
: 删除之后的任何内容:
sed 's/:.*//'
在这种情况下具有cut -d: -f1
相同的效果
这可能比斯蒂芬的解决方案慢:
grep -m1 -n '^c' "${varFileLog}" | cut -d: -f1
Run Code Online (Sandbox Code Playgroud)
您需要grep
通过将匹配锚定到行的开头来告诉 \xe2\x80\x9cthat 应该位于行的开头 \xe2\x80\x9d 约束^
:
trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")\n
Run Code Online (Sandbox Code Playgroud)\n然后对 \xe2\x80\x99s 输出进行后处理grep
以仅保留行号:
trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")\ntrimLineNum="${trimLineNum%%:*}"\n
Run Code Online (Sandbox Code Playgroud)\n请注意,这-m
是一个 GNU 扩展(对于 GNU grep
,您需要--
即使^c
不以 开头--
,以防$varFileLog
其本身可能以 开头-
,因为 GNUgrep
即使在非选项参数之后也接受选项)。标准情况下,您可以将输出head -n 1
通过管道传输到。
如果没有匹配,第一个命令将返回 false/失败,而第二个命令将始终返回 true,除非您启用pipefail
多个 shell(包括bash
.