我有这个代码:
#!/bin/bash
# ~/test.sh
if [[ -p /dev/stdin ]]; then
var="-"
else
var="$1"
fi
l=$(cat -n "$var" | wc -l)
c=$(cat -n "$var" | wc -m)
echo l=$l
echo c=$c
如果我运行:
$ ./test.sh file.txt
l=73
c=4909 # it is correct
但是如果
cat file.txt | ./test.sh
l=73
c=0 #why i have 0???
我不明白为什么我有c=0
cat file.txt | cat -n - | wc -c
作品;那么我的代码有什么问题呢?
我做错了什么?
我怎样才能使它正常工作?
当您通过管道而不是打开文件时,不同之处在于管道输入或stdin
是一个流(无需重新查找即可启动(。
l=$(cat -n "$var" | wc -l)
消耗整个流来计算行数。
到达时:
c=$(cat -n "$var" | wc -m)
stdin
流已经全部被先前的行计数所消耗。它已无剩余计数,因此返回0
。
幸运的是,wc
可以在同一次运行中同时执行这两项操作,然后您可以读取这样的结果值:
#!/usr/bin/env bash
var=${1--}
if [ -p /dev/stdin ]; then
if [ $# -ge 1 ]; then
printf %s\n 'Need either stdin or filename argument (not both)!' >&2
exit 1
fi
elif [ $# -ne 1 ]; then
printf %s\n 'Need stdin or a single filename argument!' >&2
exit 1
fi
read -r l c _ < <(wc -lm -- "$var")
printf 'l=%dnc=%dn' "$l" "$c"
第一个cat
消耗标准输入,直到文件结束;那么就没有办法为第二CCD_ 7再次读取相同的数据。
通常的解决方案是使用临时文件;但是,如果您只想从wc
中获得不同的计数,请运行一次并从其输出中提取这两个计数。
set -- $(cat -n "${@--}" | wc -l -m)
l=$1
c=$2
还要注意参数扩展"${@--}"
是如何根据脚本是否接收到参数而扩展到"$@"
或-
的。