如何读取偶尔包含额外换行符的输入文件?

如何读取偶尔包含额外换行符的输入文件?

大多数时候,我得到的输入文件如下所示:

java-1.8.0-openjdk.x86_64  1:1.8.0.232.b09-1.el6_10        asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64 1:1.8.0.232.b09-1.el6_10        asyum:ol6_latest
kernel.x86_64              2.6.32-754.23.1.el6             asyum:ol6_latest

...我有一个 while 循环,能够使用以下代码成功捕获每行的 field1 和 field2:

f1=$(echo $line | awk '{print $1}')
f2=$(echo $line | awk '{print $2}')

但是,我偶尔会得到与此类似的输入文件:

java-1.8.0-openjdk.x86_64  1:1.8.0.232.b09-1.el6_10        asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64
                           1:1.8.0.232.b09-1.el6_10        asyum:ol6_latest
kernel.x86_64              2.6.32-754.23.1.el6             asyum:ol6_latest

(请注意,有一个额外的换行符将第 2 行分开。)

您是否有任何以编程方式处理此类输入(而不是手动清理输入文件)的提示/技巧?

答案1

这是一个仅依赖于前导空格的解决方案。它不依赖于预期的字段数量。

GNU 手册sed提供了一种“连接以空格开头的行”的方法:

sed -E ':a ; $!N ; s/\n\s+/ / ; ta ; P ; D'

该手册声称可移植(非 GNU)变体是:

sed -e :a -e '$!N;s/\n  */ /;ta' -e 'P;D'

答案2

这应该可以达到所需的效果:

#!/usr/bin/env bash

while read line; do
    declare -a array=($line)
    if  test ${#array[@]} != 3; then
        read line2
        array+=($line2)
    fi
    f1=${array[0]}
    f2=${array[1]}
    echo $f1 $f2
done

run with : test.sh < inputfile

它检查一行是否包含三个项目,如果没有,则加入下一行。

答案3

既然你awk无论如何都在使用它,为什么不完全依赖它呢?尝试

read f1 f2 <<< $(awk '{while (NF < 3) {getline X; $0 = $0 FS X};  print $1, $2}' file)

答案4

假设输入数据的每个格式正确的行都由三个单词组成(此处宽松地定义为不包含任何空白字符的字符串),您可以预处理输入数据:

<input_file tr -s '[:blank:]' '\n' | paste - - - | column -t

<newline>在这里,我们用单个替换任何空白字符(包括字符) <newline>,将结果重新排列为三个单词的行,并很好地格式化输出 - 考虑到您的问题,最后一个是不必要的装饰步骤。

相关内容