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

kra*_*erz 65 string bash

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

var=`ls "$sdir" | grep "$input"`
Run Code Online (Sandbox Code Playgroud)

伪代码:

while [ ! $var's number of lines -eq 1 ]
  do something
Run Code Online (Sandbox Code Playgroud)

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

1 不起作用

Ign*_*ams 89

行情很重要.

echo "$var" | wc -l
Run Code Online (Sandbox Code Playgroud)

  • 这有点微妙.空字符串将返回1,因为空字符串上的echo打印换行符. (30认同)
  • @Tim`echo -n`只会将计数减少一个.@lucifurious`echo $(wc -l <​​<<"$ {NONEXISTENTVAR}")`仍然给出1,而不是0 (4认同)
  • 这不是围绕命令的引用,而是围绕命令替换的引用.引号对不会干扰. (3认同)
  • 换句话说:`if [-z"$ var"]; 然后printf'%s \n''0'; else printf'%s \n'"$ {var%$'\n'}"| wc -l; fi`.尝试使用`var =`(无行),`var ='foo'`和`var = $'foo \n'`(*nix意义上的一行). (2认同)
  • 还有另一种将其放入变量的方法:`LINE_COUNT=$(wc -l &lt;​​&lt;&lt; "${var}")` (2认同)

Jul*_*ian 51

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

这有效:

echo -n "$VARIABLE" | grep -c '^'
Run Code Online (Sandbox Code Playgroud)

例如:

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
Run Code Online (Sandbox Code Playgroud)

  • 完善!这应该是公认的答案.到目前为止,它是唯一能够正确回答所有案例的问题的解决方案.感谢您展示测试用例来证明这一点. (4认同)
  • 是!我也认为这应该是公认的答案. (4认同)

spe*_*akr 21

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

wc -l <<< "$var"
Run Code Online (Sandbox Code Playgroud)

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

  • `xxd <<<''`创建这个hexdump`000000:0a`.因此,`<<<`(Here Strings)为任何内容添加换行符. (2认同)

haq*_*aqk 11

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

方法一

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

 var="${var//[!$'\n']/}"
 echo $((${#var} + 1))
Run Code Online (Sandbox Code Playgroud)

方法二

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

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

  • 方法 2 更简洁,可能更快。然而,它依赖于`IFS`。因此,设置`IFS=$'\n'` 以确保在将变量扩展为数组时将其拆分为新行:`IFS=$'\n'; var=(${var})` (2认同)

Chr*_*don 8

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


Sti*_*lez 6

@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
Run Code Online (Sandbox Code Playgroud)


小智 5

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

readarray -t tab <<<"${var}"
echo ${#tab[@]}
Run Code Online (Sandbox Code Playgroud)

readarray|mapfile是 bash 内部命令,它将输入文件(或本例中的字符串)转换为基于换行符的数组。

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

这种方法的优点是:

  • 没有外部命令(wc、grep、...)
  • 无子壳(管道)
  • 没有 IFS 问题(修改后恢复,在内部命令的命令限制范围内使用很棘手,...)