在bash中交换列

时间:2013-08-12 16:26:43

标签: linux bash shell awk

我有这个文件:

$ cat file
1515523  A45678BF141  A11269151
2234545  A45678BE145  A87979746
5432568  A45678B2123  A40629187
7234573  A45678B4154  A98879129
8889568  A45678B5123  A13409137
9234511  A45678B9176  A23589941
3904568  A45678B7123  A52329165
3234555  A45678B1169  A23589497
9643568  A45678B6123  A39969112
1234547  A45678B2132  A40579243

和这个脚本:

cat file | awk '{FS = " "} {print $1" "$3" "$5}'| awk '{
    n = split($3, a, "");
    s = "";
    for (i = 1; i <= n; i += 2) s = s a[i+1] a[i];
    print $1, substr($2, length($2)-3, 4), s
}'| cut -d" " -f3,1  >  output

当我用vi打开输出时,我有:

1515523  F141  11621915^M
2234545  E145  78797964^M
5432568  2123  04261978^M
7234573  4154  89781992^M
8889568  5123  31041973^M
9234511  9176  32859914^M
3904568  7123  25231956^M
3234555  1169  32854979^M
9643568  6123  93691921^M
1234547  2132  04752934^M

我不知道为什么我会获得^M,因为当我打算运行awk代码段时:

cat imei | awk '{FS=" "} {print $2","$1}'

输出错误,即它不交换列,因为它不打印第二列。关于可能发生的事情的任何想法?

4 个答案:

答案 0 :(得分:3)

数据文件中有回车符(^M Control-M )。它可能在某个时候来自Windows机器。

当您打印$2","$1(将$2与包含逗号然后$1的字符串连接起来时 - 我花了几个看才能看到它真正在做什么),回车使第二列覆盖第一列。

使用od -c或类似工具查看数据文件,以查看其中的回车。

您可以使用dos2unixtrvarious other techniques将文件从DOS / Windows格式转换为Unix格式。

另外,鉴于显示的数据格式,我希望不要使用-F " "(或等效的FS = " "),以便您拥有$1列,{{ 1}}和$2,这比使用如图所示的第1,3,5列更明显。如果您希望输出在列之间有两个空格,则可以将OFS设置为双空白。

答案 1 :(得分:2)

$ dos2unix file
$ awk '{split($3,a,""); print $1, substr($2,8), a[3]a[2]a[5]a[4]a[7]a[6]a[9]a[8]}' file
1515523 F141 11621915
2234545 E145 78797964
5432568 2123 04261978
7234573 4154 89781992
8889568 5123 31041973
9234511 9176 32859914
3904568 7123 25231956
3234555 1169 32854979
9643568 6123 93691921
1234547 2132 04752934

答案 2 :(得分:0)

由于您使用的是awk,因此不需要dos2unix。

只需插入

即可
 gsub(/\r/,"");

作为awk脚本中的第一个语句  它清理读入的每一行。后续匹配或处理不会得到任何“回车”字符。

答案 3 :(得分:0)

perl'one liner'怎么样(带延续线)

$ dos2unix file
$ perl -lane \
'$xxxx = substr($F[1],-4);
@c = split(//,$F[2]);
print "$F[0] $xxxx $c[2]$c[1]$c[4]$c[3]$c[6]$c[5]$c[8]$c[7]"' file