查找并报告文本文件中空行的行号

Adn*_*Ali 6 command-line text-processing

我有包含 14000 多行的文本文件。它包含一些我用于语音识别数据训练的数据。

我通过 Java 编码创建了该文件,并且由于一些语义错误,其中几行是空的。每次我运行训练时,它都会在大约 30 分钟后出现错误,抱怨有一个空行。

是否有任何代码/脚本/命令可以为我提供带有空行的行号列表,以便我可以填充这些空行并节省我的时间?

工作应该是这样的:

我会输入一个file.txt它会给我

line number 1121,1212,1450,13000 and so on ... 是空的 file.txt

在此处输入图片说明

wal*_*tor 15

您可以找到空行及其行号,

grep -E --line-number --with-filename '^$' file.txt  
Run Code Online (Sandbox Code Playgroud)

一个例子:

w3@aardvark:~(0)$ grep -E --line-number --with-filename '^$' file.txt
file.txt:1:
file.txt:3:
file.txt:4:
w3@aardvark:~(0)$ cat -n file.txt
     1  
     2  Not empty
     3  
     4  
     5  Not empty
w3@aardvark:~(0)$ 
Run Code Online (Sandbox Code Playgroud)

如果您的“空”行包含空格或制表符,请使用:

grep -E --line-number --with-filename '^\s*$' file.txt
Run Code Online (Sandbox Code Playgroud)

  • 你为什么使用`-E`?不错,虽然+1 ;) (2认同)

Zan*_*nna 7

sed将使用=命令报告行号,因此您可以使用此表达式报告空行的行号(在^(行首)和$(行尾)之间没有任何内容的行):

sed -n '/^$/=' file
Run Code Online (Sandbox Code Playgroud)

我们使用-n选项来抑制打印流(当我们使用 时=,行号与行本身分开打印,因此这里没有p命令),因此唯一的输出是匹配行的行号。

$ sed -n '/^$/=' foo 
1
3
5
7
Run Code Online (Sandbox Code Playgroud)

(如果第 1、3、5 和 7 行在 中为空foo


下面是一个示例,展示了如何获得所需的用户交互。您可以使用任何解决方案来代替sed这些结构中的表达式...

$ cat foo

2

4

6

8
Run Code Online (Sandbox Code Playgroud)

所以:

$ read -p "Enter file name: "; echo -e "The following lines are empty in "$REPLY":\n$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"
Enter file name: foo
The following lines are empty in foo:
1 3 5 7 
Run Code Online (Sandbox Code Playgroud)

tr '\n' ','用于获取逗号而不是空格)

您可以另存为脚本(我将其命名为我的empline):

#!/bin/bash
read -p "Enter file name: "
echo -e "The following lines are empty in "$REPLY":\n\
$(sed -n '/^$/=' "$REPLY" | tr '\n' ' ')"
Run Code Online (Sandbox Code Playgroud)

使脚本可执行:

chmod u+x empline
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样运行它

$ ./empline
Enter file name: foo
The following lines are empty in foo:
1 3 5 7 
Run Code Online (Sandbox Code Playgroud)

你可以跳过read线并更换"$REPLY""$1"使用文件名作为参数的位置(所以运行./empline foo)。为了简化使用,您可以创建一个函数并添加到您的末尾~/.bashrc

function empline() {
    echo -e "The following lines are empty in "$1":\n\
$(sed -n '/^$/=' "$1" | tr '\n' ' ')"
}
Run Code Online (Sandbox Code Playgroud)

这将文件名作为参数:

$ empline foo
The following lines are empty in foo:
1 3 5 7 
Run Code Online (Sandbox Code Playgroud)


Gau*_*ria 6

使用 awk

多文件输入的方法(见文章末尾)是最健壮的。

单文件输入:

awk 'BEGIN { printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt
Run Code Online (Sandbox Code Playgroud)

BEGIN部分在处理输入文件之前运行。

ARGV[1]是输入文件的名称。这对应于awk的FILENAME变量,在BEGINsection中不起作用。

!NF匹配空白行或仅包含字段分隔符的行。默认字段分隔符是空格和制表符,因此仅包含空格和制表符的行算作空。 NF(不带感叹号)匹配包含数据的行,添加会! 反转匹配。

NR是当前正在评估的输入文件的行号。 NR如果在命令行上指定了其他输入文件,则不会重置为 1。

为了防止逗号出现在第一个匹配的行号之前,请sep在打印第一个匹配之前保持未定义字符串。

END部分在处理输入文件后运行。在此示例中,它通过打印 Unix 样式的换行符干净地终止输出。

示例输出:

Line numbers of empty lines in file.txt: 8,13,15,20,25,28
Run Code Online (Sandbox Code Playgroud)

即使您最初希望它为空,在没有首先设置它的情况下使用字符串名称也有点草率。您可以sep在该BEGIN部分中将字符串显式设置为空:

awk 'BEGIN { sep="" ; printf "Line numbers of empty lines in " ARGV[1] ": " } !NF { printf sep NR ; sep="," } END { printf "\n" }' file.txt
Run Code Online (Sandbox Code Playgroud)

多文件输入:

awk 'FNR==1 && NR>1 { printf "\n" } FNR==1 { sep="" ; printf "Line numbers of empty lines in " FILENAME ": " } !NF { printf sep FNR ; sep="," } END { printf "\n" }' file1.txt file2.txt file3.txt
Run Code Online (Sandbox Code Playgroud)

FNR与 类似NR,不同之处在于FNR行号计数器在每个文件的开头重置为 1。

该部分FNR==1 && NR>1 { printf "\n" }使每个文件的输出打印在单独的行上。它打印换行符当每个的第一行的附加输入文件被处理,但不适合的第一行第一文件。

示例输出:

Line numbers of empty lines in file1.txt: 8,13,15,20,25,28
Line numbers of empty lines in file2.txt: 1,2,4,6,7,9,10
Line numbers of empty lines in file3.txt: 3,8,9,11,13,15
Run Code Online (Sandbox Code Playgroud)

  • 我可能会使用`FNR == 1` 和`FILENAME` 而不是`BEGIN` 和`ARGV[1]`(以及`FNR` 而不是`NR`,那么它应该可以处理多个文件)。 (2认同)

wja*_*rea 5

纯猛砸,使用示例文件foo赞纳的回答

i=0
while read line; do
    ((++i))
    if [[ $line == '' ]]; then
        echo $i
    fi
done < foo
Run Code Online (Sandbox Code Playgroud)

输出:

1
3
5
7
Run Code Online (Sandbox Code Playgroud)

或者,您可能更喜欢使用以下命令的Python 解决方案的 Bash 等效项enumerate()

cat -n foo | 
    while read -r i line; do
       if [[ $line == '' ]]; then
            echo $i
        fi
    done
Run Code Online (Sandbox Code Playgroud)