我有一个文件末尾有空白行的文件。我可以使用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