使用awk

使用awk

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

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

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

工作应该是这样的:

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

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

在此处输入图片描述

答案1

您可以使用以下代码查找空行及其行号:

grep -E --line-number --with-filename '^$' file.txt  

一个例子:

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)$ 

如果“空”行包含空格或 TAB,请使用:

grep -E --line-number --with-filename '^\s*$' file.txt

答案2

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

sed -n '/^$/=' file

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

$ sed -n '/^$/=' foo 
1
3
5
7

(如果第 1、3、5 和 7 行是空的foo


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

$ cat foo

2

4

6

8

所以:

$ 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 

(使用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' ' ')"

使脚本可执行:

chmod u+x empline

然后你可以像这样运行它

$ ./empline
Enter file name: foo
The following lines are empty in foo:
1 3 5 7 

您可以跳过该read行并替换"$REPLY""$1"以使用文件名作为位置参数(因此运行./empline foo)。为了简化使用,您可以创建一个函数并将其添加到~/.bashrc

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

这将文件名作为参数:

$ empline foo
The following lines are empty in foo:
1 3 5 7 

答案3

使用awk

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

单个文件输入:

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

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

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

!NF匹配空白行或仅包含字段分隔符的行。默认字段分隔符是空格和制表符,因此仅包含空格和制表符的行将被视为空行。 NF(不带感叹号)匹配以下行包含数据,并添加! 倒置比賽。

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

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

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

示例输出:

Line numbers of empty lines in file.txt: 8,13,15,20,25,28

在没有先设置字符串名称的情况下使用它有点草率,即使你最初为空。您可以sep在以下部分中明确将字符串设置为空BEGIN

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

多文件输入:

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

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

答案4

perl

如果行号为空 ( ),则打印 ( printf("%s\n", $.)) 行号:if /^$/

perl -ne 'printf("%s\n", $.) if /^$/' file.txt

python3

遍历start == 1文件的枚举()行,并在空时打印行号:

with open('file.txt') as f:
    for idx, line in enumerate(f, 1):
        if line.rstrip('\n') == "":
            print(idx)

相关内容