我有以下代码:
#!/bin/bash
for f in `find . ! -type d`;
do
line=`grep -i 'todo' $f | sed 's/^[ \t]*//'`
if [ $line ]; then
echo "$f:"
echo "$line"
fi
done
但是条件不能像我期望的那样工作,我需要它才能在命令返回空字符串(或什么都没有)之外的情况下工作。
答案 0 :(得分:4)
正如Alberto所指出的,通常使用-n
检查字符串是否具有非零长度,但在字符串可能为空或仅包含空格的情况下,您需要引用变量:
if [ -n "$line" ] # ...
同样,您可以使用-z
检查其长度是否为零:
if [ -z "$line" ] # ...
当更有意义时,也支持否定:
if [ ! -z "$line" ] # ...
编辑:由于你正在使用bash,你实际上可以使用其他一些不错的功能,例如:
[[ expr ]]
)和[[ cat =~ ca[bat] ]]
)有关详细信息,请参阅man bash
中的conditional constructs部分。
答案 1 :(得分:3)
一些想法:
$f
行中的grep
来处理名称中包含空格的文件。-f
而不是! -d
,否则你的发现可能会挂起来。\t
转义不能作为选项卡匹配,它在测试用例文件行中消耗了一个前导t,所以我只是在脚本中插入一个原始制表符而不是。您的脚本会略有不同:
find . -type f | while read f
do
# raw tab in here ------------------- v
line=`grep -i 'todo' "$f" | sed 's/^[ ]*//'`
if [[ $line ]]; then
echo "$f:"
echo "$line"
fi
done
答案 2 :(得分:2)
旧的学校符号(可用于Bourne Shell等古老的东西,而不是Korn shell等古老的东西)是:
for f in `find . ! -type d`
do
line=`grep -i 'todo' $f | sed 's/^[ \t]*//'`
if [ -n "$line" ]
then
echo "$f:"
echo "$line"
fi
done
但是,您可以使用以下方法加快整体处理速度:
find . ! -type d -print0 | xargs -0 grep -i 'todo' /dev/null |
perl -p -e '($name) = split /:/;
if ($saved ne $name) { $saved = $name; print "$name:\n"; }
s/^$name:\s*//;'
修改find
以处理名称中的空格; xargs
还处理名称中的空格,并在/ dev / null和一些文件上运行grep
命令 - 这可确保匹配的行前面有文件名。 perl
脚本在第一个冒号处拆分行 - 因此包含冒号的文件名不是好消息。它将该名称与之前保存的名称进行比较;如果它们不同,那么它会打印出新名称,冒号和换行符,以便为您提供文件标题。然后在(自动)打印行之前删除文件名和尾随空格。 (不要在Perl中使用'-w';它会抱怨$ saved未初始化。如果必须(这是一个好习惯),请添加BEGIN { $saved = ""; }
。)
这可能比shell循环执行得更好,因为它只调用grep几次而不是每个文件调用一次,并且根本不调用sed
(而不是每个文件调用一次)。
答案 3 :(得分:1)
if [ -n $line ]
检查$line
是否为空字符串。
答案 4 :(得分:0)
这是我喜欢的:
if [ ${PIPESTATUS[0]} -eq 0 ]; then echo lines found; fi
它采用grep
的退出状态。手册页告诉:
EXIT STATUS
Normally, the exit status is 0 if selected lines are found and 1 otherwise.
答案 5 :(得分:0)
如果可以,请使用POSIX字符类:
# cf. http://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes
sed 's/[[:blank:]]/-wasTabOrSpace-/g' <<< $'abc\t def'
答案 6 :(得分:0)
由于我们分别因为`...`或$(...)构造而有子shell,我们可以像使用指定的基于PIPESTATUS的退出代码的任何其他(父)shell一样退出子shell! : - )
# simple test
var="$(echooo hello 2>/dev/null | cat)"
echo ${PIPESTATUS[0]} # 0
var="$(echooo hello 2>/dev/null | cat; exit ${PIPESTATUS[0]})"
echo ${PIPESTATUS[0]} # 127