使用 Awk 合并文件中的列

使用 Awk 合并文件中的列

输入:

ABC,SSSD,12345,NSS,12345,xxx,TS11
,,,,,,TS21
,,,,,,TS22
,,,,,,BS26
,,,,,,GPRS
ABC,SSSD,12356,NSS,12356,xxx,TS11
,,,,,,TS21
,,,,,,TS22
,,,,,,GPRS
,,,,,,BS26

输出:

ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS
ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26

我已经尝试编写下面的脚本。但这是性能密集型的:

#!/bin/bash
head -2 $1 | tail -1 >> $1"_output"
sed '1,2d' $1 > temp$1.txt
cp temp$1.txt $1
rm -f temp$1.txt
while IFS='' read -r line || [[ -n $line ]]; do
    #    echo "main line -- "$line
    #    echo "prev line -- "$prevLine
    service=`echo $line | cut -d "," -f1`
    value=`echo $line | cut -d "," -f7`
    if [ "$service" != "" ]
    then
        if [ "$prevLine" != "" -a "$mvalue" != "" ]
        then
            echo $prevLine$mvalue >> $1"_output"
        fi
        prevLine=$line
        mvalue=""
    else
        #echo $value
        mvalue=$mvalue"|"$value
        #echo $mvalue
    fi
done < "$1"
echo $prevLine$mvalue >> $1"_output"

有人可以建议一种更好的方法来使用 awk 或任何更好的方法来做到这一点吗?

答案1

如果您对空格不太挑剔,可以使用两个 awk 规则来完成,如下所示:

 awk '$1 { printf "\n" $0 } !$1 { printf OFS $7 }' FS=, OFS='|' infile

这会在输出的开头留下一个空行,并在末尾遗漏一个空行。要修复此问题,请添加ifEND子句:

awk '$1 { if(NR>1) printf "\n"; printf $0 } !$1 { printf OFS $7 } END { printf "\n" }' FS=, OFS='|' infile

输出:

ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS
ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26

编辑 - 注意 $0 中的 %

正如 Glenn 在评论中指出的那样,如果您的行包含,则使用格式字符串进行%调用会更安全,例如:printf

awk '$1 { if(NR>1) printf "\n"; printf "%s", $0 } !$1 { printf OFS"%s", $7 } END { printf "\n" }' FS=, OFS='|' infile

答案2

只要要合并的行数是恒定的,awk就可以通过查看行号来确定它是什么类型的行:

$ awk -F, '1==NR%5 { printf $0 "|";next } { printf $7 (NR%5?"|":"\n") }' DATA
ABC,SSSD,12345,NSS,12345,xxx,TS11|TS21|TS22|BS26|GPRS
ABC,SSSD,12356,NSS,12356,xxx,TS11|TS21|TS22|GPRS|BS26

答案3

其他sed

sed ':;N;s/\n,,,*/|/;t;P;D' file

答案4

如果它的行数始终相同 (5),则paste和的组合sed可以执行以下操作:

paste -d',' - - - - - <file | sed 's/,\{2,\}/|/g'

将 1) 将paste5 行合并,为分隔符,2) 用一根竖线替换多个(2 个或更多)逗号

相关内容