逐行迭代文件时跳过空行

34

我正在逐行迭代文件,并将每个单词放入数组中,这样做是有效的。但它也会捕获空行并将其作为数组中的一个项,如何跳过空行?

示例文件

      Line 1
line 2

line 3
        line 4 

line 5
   line 6

我的代碼

while read line ; do
            myarray[$index]="$line"
            index=$(($index+1))
    done < $inputfile

可能的伪代码

while read line ; do
           if (line != space);then
            myarray[$index]="$line"
             fi
            index=$(($index+1))
    done < $inputfile
7个回答

40

更优雅一些:

echo "\na\nb\n\nc" | grep -v "^$"

cat $file | grep -v "^$" | next transformations...

17
为什么要用cat命令来配合grep命令?直接使用grep -v "^$" "$inputfile"不也可以吗? - go2null
3
由于输出的目的是要传输到另一个操作,因此最好管道输入文件而不是提供它作为参数。这样,您可以直接从左到右读取数据流,而不是从中间开始向左跳然后向右跳转。诚然,这浪费了4个字符和几毫秒,但我认为这并不是什么大问题。此外,以这种方式呈现可以轻松地在管道的第一阶段中替换输入来源。 - pyrocrasty
1
$file 应该在这里使用双引号。无法保证文件名不包含空格。 - pyrocrasty
我不清楚原帖作者如何实际使用这个答案。将最后一行替换为“$inputfile”? - Noumenon
1
在这个例子中,echo "\na\nb\n\nc" 可能会让人感到困惑,因为 echo 默认情况下不处理控制字符(但这取决于你使用的是哪个 echo:shell 内置的还是 $PATH 中找到的);由于我们正在谈论 bash,更好的例子是:printf '\na\nb\n\nc' | grep -v '^$'(或等效地,... | grep '.')。 - michael
显示剩余2条评论

29

请按照您的伪代码实施相同的测试:

while read line; do
    if [ -n "$line" ]; then
        myarray[$index]="$line"
        index=$(($index+1))
    fi
done < $inputfile

测试-n表示true如果不为空

您还可以使用表达式[ "x$line" = x ]test "x$line" = x来测试行是否为空。

然而,任何包含空格的行将不会被视为空。如果这是一个问题,您可以使用sed从输入中删除这样的行(包括空行),在它们传递给while循环之前,如下所示:

sed '/^[ \t]*$/d' $inputfile | while read line; do
    myarray[$index]="$line"
    index=$(($index+1))
done

3
简化后的翻译:如果 [ "$line" ] 存在,则执行下一步操作。 - SzG
1
是的,这在Linux/bash上可以工作...但不确定其他/旧的Unix和shell是否适用。autoconf工具特别使用“test“x$line”= x”的形式以实现最大的可移植性。 - isedev
我能在sed中添加一些内容吗?如果一行开头有一个空格,则删除该空格或直到第一个字母的所有空格。 - MAXGEN
你可以使用以下命令:sed -e '/^[ \t]*$/d' -e 's/^[ \t]*//' 来删除空白或全空行,并在一行中移除所有非空格字符前的前导空格。 - isedev
循环执行时,插入echo $line,你会看到结果。我认为你的问题是myarray只在循环内部是局部变量,在循环外部不可见。 - isedev
显示剩余4条评论

12

首先,使用sed命令去除空行。

for word in `sed '/^$/d' $inputfile`; do
    myarray[$index]="$word"
    index=$(($index+1))
done

5

cat -b -s file | grep -v '^$'

我知道这个问题已经解决了,但是,如果有人需要输出带有行号的文本,同时忽略空行,可以使用上面的命令。


作为“cat”的替代品(它会重新格式化输出,而不是通常所需的),“grep”也可以添加行号。如果匹配每一行,则不会跳过任何数字:例如,“grep -v'^$' file | grep -n .”(您可以通过“sed”将冒号(“:”)转换为其他内容) - michael

3

使用grep去除空行:

for word in $(cat ${inputfile} | grep -v "^$"); do
   myarray[$index]="${word}"
   index=$(($index+1))
done

2
为什么要用 cat 命令来配合 grep 呢?使用 grep -v "^$" "$inputfile" 不是同样可以吗? - go2null
两种都是正确的。我只是习惯使用“cat”,因为有时候我需要用“echo”代替“cat”。 - NFTX

2

与调用外部命令如sedgrep的解决方案相比,此版本非常快。同时,它跳过只包含空格的行,这些行不需要为空就可以跳过。

#!/bin/bash

myarray=()
while read line
do
    if [[ "$line" =~ [^[:space:]] ]]; then
        myarray+=("${line}")
    fi
done < test.txt

for((i = 0; i < ${#myarray[@]}; ++i))
do
    echo ${myarray[$i]}
done

2

以下是我一直以来的方法。不需要调用grep,也不需要两个缩进级别。

while read line; do
 # skip  empty lines
 [ -z "$line" ] && continue
 echo "processing $line"
done < "$inputfile"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接