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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6314679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 01:08:02  来源:igfitidea点击:

In bash, how do I count the number of lines in a variable?

bashstring

提问by krack krackerz

I have a variable which has a string stored in it and need to check if it has lines in it:

我有一个变量,其中存储了一个字符串,需要检查它是否有行:

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

pseudo-code:

伪代码:

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

That's my idea on how to check it. echo $var | wc -ldoesn't work - it always says 1, even though it has 3.

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

echo -edoesn't work as well.

echo -e也不行。

回答by Ignacio Vazquez-Abrams

Quotes matter.

报价很重要。

echo "$var" | wc -l

回答by Julian

The accepted answer and other answers posted here do not work in case of an empty variable (undefined or empty string).

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

This works:

这有效:

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

For example:

例如:

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

回答by speakr

Another way using here stringsin bash:

在 bash 中使用here 字符串的另一种方法:

wc -l <<< "$var"

As mentioned in this comment, an empty $varwill result in 1 line instead of 0 lines because here stringsadd a newline character in this case (explanation).

如此评论中所提到的,空$var将导致 1 行而不是 0 行,因为在这种情况下,这里的字符串会添加一个换行符(解释)。

回答by Christopher Brunsdon

You can substitute the "wc -l" with "wc -w" to rather count the number of words instead of lines. This will not count any new lines and can be used to test if your original results are empty before you continue.

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

回答by Stilez

A simpler version of @Julian's answer, that works for all strings, with or without trailing \n (it does count a file containing just a single trailing \n as empty):

@Julian 答案的更简单版本,适用于所有字符串,无论是否带有尾随 \n(它确实将仅包含单个尾随 \n 的文件计为空):

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

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

  • Returns zero: unset variable, empty string, string containing bare newline
  • Returns 1: any non-empty line, with or without trailing newline
  • etc
  • 返回零:未设置变量、空字符串、包含裸换行符的字符串
  • 返回 1:任何非空行,带或不带尾随换行符
  • 等等

Output:

输出:

# 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

回答by haqk

No one has mentioned parameter expansion, so here are a couple of ways using pure bash.

没有人提到参数扩展,所以这里有几种使用纯 bash 的方法。

Method 1

方法一

Remove non-newline characters, then get string length + 1. Quotes are important.

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

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

Method 2

方法二

Convert to array, then get array length. For this to work, don't use quotes.

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

 set -f # disable glob (wildcard) expansion
 IFS=$'\n' # let's make sure we split on newline chars
 var=(${var})
 echo ${#var[@]}

回答by Jonathan Matthews

The top voted answers fail if no results were returned by a grep.

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

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

This is the wrongway to do it:

这是错误的方式做到这一点

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

There will tell us, there is 1Wiggumin the list, even if there aren't any.

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

Instead, you need to do one extra check to see if the variable is empty (-z, as in "is zero"). If grep didn't return anything, the variable will be empty.

相反,您需要进行一次额外检查以查看变量是否为空(-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";

回答by adrenochrome

Another method to count number of lines in a variable - assuming you did check it was successfully filled or it is not empty, for that just check $? after varsubshell result affectation - :

计算变量中行数的另一种方法 - 假设您确实检查了它是否已成功填充或它不为空,为此只需检查 $? 在varsubshel​​l 结果影响 - 之后:

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

readarray|mapfileis bash internal command which converts input file, or here stringin this case, to array based on newlines.

readarray|mapfile是 bash 内部命令,它根据换行符将输入文件或这里的字符串转换为数组。

-tflag prevents storing newlines at end of array's cells, useful for later use of stored values

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

Advantages of this method are :

这种方法的优点是:

  • no external command (wc, grep, ...)
  • no subshell (pipe)
  • no IFS issues (restore after modification, tricky to use with command-limited scope on internal commands, ...)
  • 没有外部命令 (wc, grep, ...)
  • 没有子外壳(管道)
  • 没有 IFS 问题(修改后恢复,在内部命令的命令限制范围内使用起来很棘手,......)