shell小技巧(三十三)把一个文本文件行和列转置

即行变为列,列变为行。
每行的列以空格分隔,且每行列数相等
例如:源文件log5.txt内容

no name age sex

x1  alice 21 f

x2  jack  30  m

x3  tom   22 m

x4  xxx   19 f

代码如下:

方法1:

#!/bin/bash

a=1

while read  line

do

    var=($line)

    x=${#var[*]}

    for ((j=0;j

        echo  ${var[$j]} >> ${j}.txt

    done

   let a=a+1 

done < log5.txt

for ((m=0;m

   cat "${m}.txt" | tr "\n" " "

   echo -e "\n"

done

执行结果:

no x1 x2 x3 x4 

name alice jack tom xxx 

age 21 30 22 19 

sex f m m f 

总结:

基本思路是按行读取内容,每列按顺序存入有序号的文件中。循环结束,同列内容已经存入形同文件。

再进行一次循环,按顺序读取文件,并将文件内容转化为1行输出,最后添加换行符。循环将文件顺序输出。

本例用到了循环、数组、分解字符串等技巧。

今天状态欠佳,代码写的时间长也并非最佳方案。失败的一天。


后补:

输出部分还可以按如下方法实现:

方法1a:

combine="paste -d \" \" "

for ((m=0;m     combine=$combine" "${m}.txt
done
echo $combine |bash

这里用了之前的技巧中没有使用过的paste命令

方法1b:

awk也可以实现,不过只能同时操作2个文件,所以还需耍个小技巧。

cat 0.txt > t1.txt
for ((m=1;m   let n=m+1 
  awk 'NR==FNR{a[NR]=$0}NR>FNR{print a[FNR],$0}' t${m}.txt ${m}.txt > t${n}.txt
done
cat t${n}.txt

awk将两个文件顺序处理,处理第一个文件时将每一行写入a数组,处理第二个文件时NR会大于FNR,此时打印数组a和第二个文件的当前行。因为文件行数一样,所以达成预定效果。

方法2:来自互联网的代码,使用awk完成
awk '{
    for (i=1;i<=NF;i++){
        if (NR==1){
            res[i]=$i
        }
        else{
            res[i]=res[i]" "$i
        }
    }
}END{
    for(j=1;j<=NF;j++){
        print res[j]
    }
}' log5.txt
说明:

当处理第一行时用数组存储每一个列值;从第二行开始,列值追加在数组后,中间加空格。

方法3:依旧使用循环,但不使用文件仅使用变量实现

#!/bin/bash
a=1
while read  line
do
    var=($line)
    x=${#var[*]}
    if [ $a -eq 0 ];then
       var1=($line)
    else
      for ((j=0;j #        echo $j
        var1[j]=${var1[j]}" "${var[$j]}
      done
    fi
   let a=a+1 
done < log5.txt
#t=$(cat log5.txt |wc -l )
#echo $t
for ((m=0;m     echo ${var1[m]}
done
 

你可能感兴趣的:(Shell技巧)