将wc命令的结果作为变量

36

我想使用来自'wc'的行作为变量。例如:

echo 'foo bar' > file.txt
echo 'blah blah blah' >> file.txt
wc file.txt

2  5 23 file.txt

我想要像$lines, $words, 和 $characters 这样的变量与值2, 5, 和 23 关联起来。在bash中我该怎么做?

7个回答

47

使用纯Bash:(没有awk)

a=($(wc file.txt))
lines=${a[0]}
words=${a[1]}
chars=${a[2]}

这个方法使用了bash的数组. a=(1 2 3) 创建了一个包含元素1、2和3的数组。然后我们可以使用语法${a[indice]}来访问不同的元素。

替代方案:(基于gonvaled解决方案)

read lines words chars <<< $(wc x)

或者在sh中:

a=$(wc file.txt)
lines=$(echo $a|cut -d' ' -f1)
words=$(echo $a|cut -d' ' -f2)
chars=$(echo $a|cut -d' ' -f3)

你能解释一下为什么这个代码可以工作吗?特别是第一行额外的括号有什么作用?如果没有它们,代码就无法正常工作,所以它们似乎非常重要。 - Konrad Rudolph
在bash中,外部的(...)创建一个数组,后面的行对其进行索引。否则,结果只是三个数字的单个字符串。 - Adrian Pronk
在这种情况下,圆括号是$(command)命令替换语法的一部分;它等同于`command`,但是圆括号符号简化了嵌套。_command_运行在子shell中,并且命令替换的文本将被_command_的输出替换,就好像你已经键入了它一样。 - Thom Boyer
“几乎就像”是因为a=x y zx分配给a,然后运行命令y za=(x y z)xyz分配给数组a,但是您不必像a=($(echo x y z))那样输入额外的括号,因为单词拆分稍后发生。 - Thom Boyer

18

还有其他解决方案,但我通常使用的一个简单方法是将wc的输出放入临时文件中,然后从那里读取:

wc file.txt > xxx
read lines words characters filename < xxx 
echo "lines=$lines words=$words characters=$characters filename=$filename"
lines=2 words=5 characters=23 filename=file.txt

这种方法的优点是您不需要为每个变量创建多个awk进程。缺点是您需要一个临时文件,之后您应该删除它。

请注意:这样做是无效的:

wc file.txt | read lines words characters filename

问题在于管道输入到read时会创建另一个进程,在那里更新的变量无法在调用shell中访问。

编辑:添加arnaud576875的解决方案:

read lines words chars filename <<< $(wc x)

无需写入文件(也不存在管道问题)即可运行。它是特定于bash的。

来自Bash手册:

Here Strings

   A variant of here documents, the format is:

          <<<word

   The word is expanded and supplied to the command on its standard input.

关键是“单词已展开”这一点。


比我的好,但你不需要文件 xxx 或文件名:wc < file.txt | read lines words characters - Adrian Pronk
@Adrian:请看我上面的评论:管道会在另一个进程中创建变量,因此在调用 shell 中不可用。 - blueFast
8
read lines words chars <<< $(wc x) 可以在不写入文件的情况下工作(并且不会出现管道问题)。 - Arnaud Le Blanc
@gonvaled: 哦,是的,那个老陷阱。@arnaud576875: 我以前没见过 <<< - Adrian Pronk

4
lines=`wc file.txt | awk '{print $1}'`
words=`wc file.txt | awk '{print $2}'`
...

如果您在意性能,您也可以先将wc结果存储在某个地方,然后再解析它。


4
只是为了增加另一种变体 -
set -- `wc file.txt`
chars=$1
words=$2
lines=$3

这显然破坏了$*和相关变量。与其他一些解决方案不同,这种方法可以在其他Bourne shell中使用。

4

我想将csv文件的数量存储在一个变量中。以下对我有用:

CSV_COUNT=$(ls ./pathToSubdirectory | grep ".csv" | wc -l | xargs)
  • xargs 去除了 wc 命令中的空格
  • 我在不同于 csv 文件所在文件夹的位置运行了这个 bash 脚本。因此,需要指定子目录的路径。

0

你可以通过打开子 shell 将输出分配给变量:

$ x=$(wc some-file)
$ echo $x
1 6 60 some-file

现在,为了获取单独的变量,最简单的选择是使用 awk

$ x=$(wc some-file | awk '{print $1}')
$ echo $x
1

0
declare -a result
result=( $(wc < file.txt) )
lines=${result[0]}
words=${result[1]}
characters=${result[2]}
echo "Lines: $lines, Words: $words, Characters: $characters"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接