我有一个文件末尾有空白行的文件。我可以使用grep文件名作为脚本中的变量来传递文件末尾的空行数吗?
grep@MichaelJohn在我的书中获得纯正。
我有一个文件末尾有空白行的文件。我可以使用grep文件名作为脚本中的变量来传递文件末尾的空行数吗?
grep@MichaelJohn在我的书中获得纯正。
Answers:
如果空白行仅在末尾
grep -c '^$' myFile
要么:
grep -cx '' myFile
grep -cv . myFile是另一种编写方法(适用于代码高尔夫球手)。但是我找到了一个解决方案,grep如果文件中的任何地方都有空行。
grep -cv .还将计算仅包含不构成有效字符的字节的行。
只是为了好玩,有些怪异sed:
#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l
说明:
/./处理具有任何字符的行,因此/./!处理非空行;对于这些,H命令将它们附加到保留空间。因此,如果我们为每个空行在容纳空间中增加了一行,则总比空行数多一行。我们稍后会照顾。//h空模式与最后一个正则表达式匹配,该正则表达式可以是任何字符,因此可以通过命令将所有非空行都寻址并移动到保留空间,h以将收集到的行“重置”为1。在添加下一个空行时,如预期的那样,将再次出现两个。$!d停止脚本,除了最后一行以外的所有行都没有输出,因此更多命令仅在最后一行之后执行。因此,无论我们在保留空间中收集的任何空行都位于文件的末尾。好。//d:d仅对非空行再次执行该命令。因此,如果最后一行不为空,sed则将退出而没有任何输出。零线。好。x 交易所拥有空间和图案空间,因此收集的线现在在图案空间中要处理。s/\n//。wc -l。一些更多的GNU tac/ tail -r选项:
tac file | awk 'NF{exit};END{print NR?NR-1:0}'
要么:
tac file | sed -n '/[^[:blank:]]/q;p' | wc -l
注意在输出:
printf 'x\n '
也就是说,在最后一个完整行之后有一个多余的空格(有些人可以将其视为额外的空白行,但是根据POSIX文本的定义,它不是有效的文本),则这些空格将为0。
POSIXly:
awk 'NF{n=NR};END{print NR-n}' < file
但这意味着完整读取文件(tail -r/ tac将从可搜索文件的末尾开始读取文件)。给出1的输出printf 'x\n '。
当您实际上在寻求grep解决方案时,我添加了一个仅依赖于GNU 的解决方案grep(好的,还使用了shell语法和echo...):
#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))
我在这是要干嘛?$(grep -c ".*" "$1")计算文件中的所有行,然后我们减去文件后没有尾随的空行。
以及如何获得这些?$(grep -B42 . "$1"会grep所有非空行和它们前面的42行,因此只要不空行之前不超过42个连续的空行,它将打印所有内容直到最后一个非空行。为了避免该限制,我将其$(grep -cv . "$1")作为-B选项的参数,即空行的总数,因此始终足够大。这样,我已经删除了尾随的空行,可以|grep -c ".*"用来计算行数。
很棒,不是吗?(-;
tac | grep,第一个非空白-m -A 42,然后减一个。我不确定哪种方法更有效,但是您也可以wc -l | cut -d' ' -f1代替空白行呢?
tac,wc和cut,但在这里我想对自己限制grep。你可以称之为反常,我称之为运动。(-;
另一个awk解决方案。k每当有非空白行时,此变化都会重置计数器。然后,每一行使计数器递增。(因此,在第一条非空白长度行之后k==0。)最后,我们输出已计数的行数。
准备数据文件
cat <<'X' >input.txt
aaa
bbb
ccc
X
计算样本中的尾随空白行
awk 'NF {k=-1}; {k++}; END {print k+0}' input.txt
3
在此定义中,空白行可能包含空格或其他空白字符;它仍然是空白。如果您真的想计算空行而不是空白行,请更改NF为$0 != ""。
$0 > ""呢 这种使用方式的strcoll()效率要比许多实现$0 != ""中的使用效率低memcmp()(strcoll()尽管POSIX要求使用)。
$0 > ""可能与有所不同$0 != ""。awk无论如何,我还是倾向于将其视为“慢”运算符(例如,如果我知道输入的数据集很大,并且处理时间很紧迫,那么我将看到我可以做些什么来减少awk必须处理的数量-我grep | awk在这种情况下使用了结构)。但是,快速浏览一下我假定的POSIX定义后,看不到对strcoll()或的任何引用memcmp()。我想念什么?
a <= b && a >= b不一定与相同a == b。哎哟!
awk或bash(其[[ a < b ]]在GNU系统例如是en_US.UTF-8语言环境运营商)为①VS ②的实例(bash,没有的<,>,=返回对于那些真)。可以说这是在这些区域设置超过在bash / awk中定义的错误
IIUC,下面的脚本count-blank-at-the-end.sh可以完成这项工作:
#!/usr/bin/env sh
count=$(tail -n +"$(grep . "$1" -n | tail -n 1 | cut -d: -f1)" "$1" | wc -l)
num_of_blank_lines=$((count - 1))
printf "%s\n" "$num_of_blank_lines"
用法示例:
$ ./count-blank-at-the-end.sh FILE
4
我测试了它GNU bash,Android mksh并在ksh。
替代Python解决方案:
样本input.txt:
$ cat input.txt
aaa
bbb
ccc
$ # command line
那个行动:
python -c 'import sys, itertools; f=open(sys.argv[1]);
lines=list(itertools.takewhile(str.isspace, f.readlines()[::-1]));
print(len(lines)); f.close()' input.txt
输出:
3
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile