在bash中,我如何计算变量中的行数?

时间:2011-06-11 07:22:05

标签: bash string

我有一个var,其中包含一个字符串,需要检查其中是否有行:

var=`ls "$sdir" | grep "$input"`

伪代码:

while [ ! $var's number of lines -eq 1 ]
  do something

这就是我关于如何检查的想法,echo $var | wc -l不起作用,它总是说1即使它有3

echo -e不起作用

9 个答案:

答案 0 :(得分:82)

行情很重要。

echo "$var" | wc -l

答案 1 :(得分:47)

此处发布的已接受答案和其他答案在空变量(未定义或空字符串)的情况下不起作用。

这有效:

echo -n "$VARIABLE" | grep -c '^'

例如:

ZERO=
ONE="just one line"
TWO="first
> second"

echo -n "$ZERO" | grep -c '^'
0
echo -n "$ONE" | grep -c '^'
1
echo -n "$TWO" | grep -c '^'
2

答案 2 :(得分:20)

另一种在bash中使用 here strings 的方式:

wc -l <<< "$var"

this comment中所述,空$var将导致1行而不是0行,因为 here strings 在这种情况下添加换行符({{3} })。

答案 3 :(得分:8)

您可以将“wc -l”替换为“wc -w”来计算单词数而不是行数。这不会计算任何新行,并且可以用来测试您的原始结果是否为空,然后再继续。

答案 4 :(得分:3)

如果grep没有返回任何结果,则最高投票答案会失败。​​

Homer Simpson
Marge Simpson
Bart Simpson
Lisa Simpson
Ned Flanders
Rod Flanders
Todd Flanders
Moe Szyslak

这是the wrong way to do it

wiggums=$(grep -iF "Wiggum" characters.txt);
num_wiggums=$(echo "$wiggums" | wc -l);
echo "There are ${num_wiggums} here!";

我们会告诉我们,列表中有1 Wiggum ,即使没有。

相反,您需要进行一次额外检查以查看变量是否为空(-z,如“为零”)。如果grep没有返回任何内容,则该变量将为空。

matches=$(grep -iF "VanHouten" characters.txt);

if [ -z "$matches" ]; then
    num_matches=0;
else
    num_matches=$(echo "$matches" | wc -l);
fi

echo "There are ${num_matches} VanHoutens on the list";

答案 5 :(得分:3)

@Julian答案的简单版本,适用于所有带有或不带有尾随\ n的字符串(它会将仅包含一个尾随\ n的文件计为空):

printf "%s" "$a" | grep -c "^"

  • 返回零:未设置变量,空字符串,包含裸换行符的字符串
  • 返回1:任何非空行,带有或不带有尾随换行符

输出:

# a=
# printf "%s" "$a" | grep -c "^"
0

# a=""
# printf "%s" "$a" | grep -c "^"
0

# a="$(printf "")"
# printf "%s" "$a" | grep -c "^"
0

# a="$(printf "\n")"
# printf "%s" "$a" | grep -c "^"
0

# a="$(printf " \n")"
# printf "%s" "$a" | grep -c "^"
1

# a="$(printf " ")"
# printf "%s" "$a" | grep -c "^"
1

# a="aaa"
# printf "%s" "$a" | grep -c "^"
1

# a="$(printf "%s" "aaa")"
# printf "%s" "$a" | grep -c "^"
1

# a="$(printf "%s\n" "aaa")"
# printf "%s" "$a" | grep -c "^"
1

# a="$(printf "%s\n%s" "aaa" "bbb")"
# printf "%s" "$a" | grep -c "^"
2

# a="$(printf "%s\n%s\n" "aaa" "bbb")"
# printf "%s" "$a" | grep -c "^"
2

答案 6 :(得分:2)

没有人提到参数扩展,因此这是使用纯bash的几种方法。

方法1

删除非换行符,然后获取字符串长度+1。引号很重要

 var="${var//[!$'\n']/}"
 echo $((${#var} + 1))

方法2

转换为数组,然后获取数组长度。 为此,请不要使用引号

 var=(${var})
 echo ${#var[@]}

答案 7 :(得分:2)

另一种计算变量行数的方法-假设您确实检查了它是否已成功填充或它不是空的,那么只需检查$?在 var 子外壳结果影响-之后::

readarray -t tab <<<"${var}"
echo ${#tab[@]}

readarray | mapfile 是bash内部命令,可将输入文件(在这种情况下为此处为字符串)转换为基于换行符的数组。

-t 标志可防止在数组单元格的末尾存储换行符,这对于以后使用存储值很有用

此方法的优点是:

  • 没有外部命令(wc,grep等)
  • 没有子壳(管道)
  • 没有IFS问题(修改后还原,难以与内部命令的命令限制范围一起使用,...)

答案 8 :(得分:1)

要避免在“ wc -l”命令中使用文件名:

lines=$(< "$filename" wc -l)
echo "$lines"