将文本列表连接成以逗号分隔的 6 组文本

将文本列表连接成以逗号分隔的 6 组文本

我有一个文件 test.txt,其中包含大量条目,下面是其示例。

Afghanistan
Albania
Algeria
Andorra
Angola
Antigua and Barbuda
Argentina
Armenia
Australia
Austria
Azerbaijan
The Bahamas
Bahrain
Bangladesh
Barbados
Belarus
Belgium
Belize
Benin
Bhutan
Bolivia
Bosnia and Herzegovina
Botswana
Brazil
Brunei
Bulgaria
Burkina Faso
Burundi
Cabo Verde
Cambodia
Cameroon
Canada
Central African Republic
Chad
Chile
China
Colombia
Comoros

我可以用来cat test.txt | tr '\n' ','将新行转换为逗号分隔的列表。

但是,我希望命令将单独的列表作为一组 6 个,每个如下所示。

Afghanistan,Albania,Algeria,Andorra,Angola,Antigua and Barbuda
Argentina,Armenia,Australia,Austria,Azerbaijan,The Bahamas
Bahrain,Bangladesh,Barbados,Belarus,Belgium,Belize
and so on ...

我怎样才能在 Centos bash shell 中做到这一点?

答案1

$ paste -d, - - - - - - <file
Afghanistan,Albania,Algeria,Andorra,Angola,Antigua and Barbuda
Argentina,Armenia,Australia,Austria,Azerbaijan,The Bahamas
Bahrain,Bangladesh,Barbados,Belarus,Belgium,Belize
Benin,Bhutan,Bolivia,Bosnia and Herzegovina,Botswana,Brazil
Brunei,Bulgaria,Burkina Faso,Burundi,Cabo Verde,Cambodia
Cameroon,Canada,Central African Republic,Chad,Chile,China
Colombia,Comoros,,,,

paste命令此处用于创建以逗号分隔的六列输出。

示例中没有足够的数据来填充最后一行的最后几列,因此这些列为空。如果要删除它们,请通过管道传递结果,通过sed '$s/,*$//'该结果删除最后一行上的所有尾随逗号:

$ paste -d, - - - - - - <file | sed '$s/,*$//'
Afghanistan,Albania,Algeria,Andorra,Angola,Antigua and Barbuda
Argentina,Armenia,Australia,Austria,Azerbaijan,The Bahamas
Bahrain,Bangladesh,Barbados,Belarus,Belgium,Belize
Benin,Bhutan,Bolivia,Bosnia and Herzegovina,Botswana,Brazil
Brunei,Bulgaria,Burkina Faso,Burundi,Cabo Verde,Cambodia
Cameroon,Canada,Central African Republic,Chad,Chile,China
Colombia,Comoros

答案2

mapfile -t data < test.txt;
printf '%s,%s,%s,%s,%s,%s\n' "${data[@]}";

如果偏移量较大并且需要一个可行的解决方案,请使用 awk ,否则如果您想要纯 shell,您可能需要一些循环!

f () { 
    offset=$1;
    infile="$2";
    mapfile -t data < "$infile";
    while ((${#data[@]}));do
        line="$(printf '%s,' "${data[@]:0:offset}")";
        data=("${data[@]:offset}");
        echo "${line%,*}";
    done
}
f 5 test.txt

答案3

对于任意数量的列:

awk -v col=6 '{printf "%s%s", (NR>1) ? (NR-1) % col ? "," : RS : "", $0}
              END{if (NR) print ""}' < your-file

使用pr(假设示例中的输入不包含某些pr实现所识别的特殊序列之一;对于 GNU 序列(如在 CEntOS 上找到的),至少包括换页字符):

pr -t -a -s, -6 < your-file

使用 GNU pr,您会发现无法获得超过 36 列(72 列的一半,默认页面宽度),除非您也使用-w(或非标准-W),但随后您会得到一些截断/填充。您可以使用-J(也是 GNU 扩展)来解决这个问题,但谁知道这会带来什么其他副作用。

对于 GNU 的 45 列pr

pr -Jtas, -w90 -45

(YMMV 与其他pr实现一样,我发现该pr命令非常混乱)。

答案4

可以使用awk:

$ awk 'BEGIN{i=1;} { a[i]=a[i]","$0;if(NR%6==0){sub(",","",a[i]);print a[i];i++;} } END {if(a[i]){sub(",","",a[i]);print a[i]}}' file
Afghanistan,Albania,Algeria,Andorra,Angola,Antigua and Barbuda
Argentina,Armenia,Australia,Austria,Azerbaijan,The Bahamas
Bahrain,Bangladesh,Barbados,Belarus,Belgium,Belize
Benin,Bhutan,Bolivia,Bosnia and Herzegovina,Botswana,Brazil
Brunei,Bulgaria,Burkina Faso,Burundi,Cabo Verde,Cambodia
Cameroon,Canada,Central African Republic,Chad,Chile,China
Colombia,Comoros

或者使用 perl one-liner :

perl -a -F'\n' -00 -ne ' map { (($_ + 1)%6 == 0) ? print $F[$_]."\n" : print $F[$_].",";  } ( 0 .. @F-1); print "\n" if eof' file

相关内容