我们必须编写一个shell脚本程序,其工作原理类似于wc
命令。 接收-l
、-c
和-w
作为其选项。
抛开外壳脚本语法;我的问题是,我们可以使用sed
或grep
或anything else
来模拟wc -c
或wc -l
或wc -w
的逻辑吗?如果是,那如何?
IMP:不要在脚本中使用wc
可以通过将适当的-v
变量设置为0
来参数化的单个awk
命令:
LC_ALL=C awk -v l=1 -v w=1 -v c=1 '
{ wc+=NF; cc+=1+length($0) }
END { printf "%st%st%sn", l ? NR : "", w ? wc: "", c ? cc : ""}
' file
注意:
为简单起见,您总是得到 3 个
t
分隔的输出字段,其中未请求输出的字段为空;但是,修改它以模拟wc
的输出行为并不难。正如choroba的
grep
答案中所解释的,如果你真的想计算字节(-c
)而不是(可能是多字节)字符(-m
),你必须在awk ...
前面加上LC_ALL=C
。- 要计算字符数(相当于
wc -m
),请删除上面的LC_ALL=C
。
警告:不幸的是,这不适用于 BSDawk
,就像在 macOS 上一样,因为它不能识别 Unicode 并且总是计算字节数(尝试awk '{print length($0)}' <<<ü
)。
- 要计算字符数(相当于
wc -l
严格计算n
字符的数量,因此它不会在其输入的末尾计算不完整的行 - 缺少尾随n
的行;相比之下,上面的awk
命令确实计算该行(以及字节/字符计数中隐含的尾随换行符)。工作原理:
awk
的NF
变量包含每个输入行上的字段数,其中行默认通过任意空格分隔为字段;换句话说:默认情况下,字段是单词。$0
是手头的输入行,其length()
告诉您字符/字节数,并添加1
以考虑行尾的n
字符。- 请注意变量
wc
和cc
如何初始化,因为awk
隐式地将空/未定义的变量视为数字上下文中的0
变量(例如使用复合运算符+=
)。 NR
包含当前从 1 开始的行号,在END
块中等于输入行的总数。
使用 awk:
-l
:
awk 'END{print NR}' inFile
-w
:
awk '{words+=NF}END{print words}' inFile
-c
:
ls -l inFile | awk '{print $5}'
如果你可以使用grep
,模拟行数很容易:只需计算匹配的事情总是发生多少次:
grep -c '^' filename
这应该输出与wc -l
相同的输出(但如果文件不以换行符结尾,它可能会再报告一行)。
若要获取字数,可以使用以下管道:
grep -o '[^[:space:]]+' filename | grep -c '^'
您需要支持-o
选项的grep
,该选项将每个匹配的字符串打印到自己的行中。该表达式匹配所有非空格序列,将它们管道到我们在前面的情况中使用的序列中只是计算它们。
要获取字符数(wc -c
),您可以使用
LC_ALL=C grep -o . filename | grep -c '^'
如果您的区域设置支持 UTF-8,则需要设置 LC_ALL,否则您将计wc -m
.您需要将换行符的数量添加到输出编号中,因此
echo $(( $( grep -c '^' filename )
+ $( LC_ALL=C grep -o . filename | grep -c '^' ) ))