我有执行类似操作的代码:
#!/bin/sh
CONTENTS=$(cat "somefile")
RELEVANT_LINES=$(echo "$CONTENTS" | grep -E "SEARCHEXPR")
COUNT=$(echo "$RELEVANT_LINES" | wc -l)
令我烦恼的是,与通过将第三行替换为以下内容给出的正确输出相比,如果没有任何匹配项,此代码不会输出相同的输出:
COUNT=$(echo "$CONTENTS" | grep -E "SEARCHEXPR" | wc -l)
我最终追踪到这样一个事实:当没有任何匹配项时,RELEVANT_LINES 被设置为空字符串,而 echo 输出一行空字符串 + \n ,行数为 1。
我尝试在第三行中使用 printf 和 echo -n ,但找不到优雅的解决方法,最终使用COUNT=$(echo "$RELEVANT_LINES" | grep '0' | wc -l)
(所有行都包含零)来避免必须用正则表达式过滤整个源文件两次。
这不可能是正确的,但我无法找出正确的解决方案。
我没有放弃编写脚本,-eq ''
因为我不确定它是否会那么强大,而且我更喜欢直接使用管道来wc
获得纯粹的整洁。
有任何提示如何获取变量中的文件内容,以便在通过 grep 过滤后整齐地区分零行和一行吗? :)
答案1
使用CONTENTS
再次保存文件echo
有点多余,你可以
lines=$(cat "somefile" | grep -E "SEARCHEXPR")
更确切地说
lines=$(grep -E "SEARCHEXPR" "somefile")
如果您只想要匹配行的数量,请使用grep -c
count=$(grep -c -E "SEARCHEXPR" "somefile")
您看到的直接问题是由echo
始终输出换行符这一事实引起的。如果您从命令替换中获得至少一行,这实际上会有所帮助,因为命令替换删除尾随换行符。它也适用于尾部空行,试试这个看看:x=$(echo foo; echo; echo); echo "$x"
。
如果除了计数之外还想以其他方式处理 shell 脚本中的行,那么将文本存储在变量中可能不是最好的选择。你可以尝试
for line in $lines ; do
something with "$line"
done
但这存在未加引号的变量的常见问题,即文件名通配和空格上的分词。包含“foo bar doo”的一行将被视为三行,因为默认情况下,空格也会分开。
您可能想使用while read
循环,但为此,支持进程替换的 shell 可能会更好。看Bash常见问题解答 001和find & while 后变量没有改变和在 bash 中,在管道未设置值后读取。