Bash 重新排列文本文件中的列;“定制订单”;使用Shell脚本

Bash 重新排列文本文件中的列;“定制订单”;使用Shell脚本,bash,shell,awk,Bash,Shell,Awk,我有一个以制表符分隔的文本文件,名为“data.txt”,它看起来像 data.txt col2 col3 col4 col1 val1 val5 val9 val13 val2 val6 val10 val14 val3 val7 val11 val15 val4 val8 val12 val16 ... 我有一个数组col\u order=[col1,col2,col3,col4] 目标是使用shell脚本根据数组“col_order”

我有一个以制表符分隔的文本文件,名为“data.txt”,它看起来像

data.txt

col2   col3   col4   col1
val1   val5   val9   val13
val2   val6   val10  val14
val3   val7   val11  val15
val4   val8   val12  val16
...
我有一个数组
col\u order=[col1,col2,col3,col4]

目标是使用shell脚本根据数组“col_order”中的顺序重新排列“data.txt”中的列

最终产量

col1   col2   col3   col4
val13  val1   val5   val9
val14  val2   val6   val10
val15  val3   val7   val11
val16  val4   val8   val12
我目前的进展

awk 'BEGIN{ORS=RS="\n"; S=OFS="\t"}{for (i=1; i<=NF; i++) {f[$i] = i}{ print $(f["col1"]),$(f["col2"]),$(f["col3"]),$(f["col4"])}}' data.txt> data_corrected.txt

awk'BEGIN{ORS=RS=“\n;S=OFS=“\t”}{for(i=1;i请尝试以下内容

cat script.bash
List=( col1 col2 col3 col4 )
##echo ${List[*]}
awk -v bash_arr_val="${List[*]}" '
BEGIN{
  num=split(bash_arr_val,array," ")
  for(i=1;i<=num;i++){
    array_with_bash_values_as_index[array[i]]=i
  }
}

FNR==1{
 for(i=1;i<=NF;i++){
   if($i in array_with_bash_values_as_index){
     actual_array[array_with_bash_values_as_index[$i]]=i
   }
 }
}
{
 for(i=1;i<=num;i++){
   printf("%s%s",$actual_array[i],i==NF?ORS:OFS)
 }
}
'  Input_file

Ed Morton编辑变量名称建议:

$ cat tst.awk
BEGIN{
    numOutFlds = split(bash_arr_val,outNr2name)
    for ( outNr=1; outNr<=numOutFlds; outNr++ ) {
        fldName = outNr2name[outNr]
        name2outNr[fldName] = outNr
    }
}

FNR==1 {
    for ( inNr=1; inNr<=NF; inNr++ ) {
        fldName = $inNr
        outNr = name2outNr[fldName]
        outNr2inNr[outNr] = inNr
    }
}
{
    for ( outNr=1; outNr<=numOutFlds; outNr++ ) {
        inNr = outNr2inNr[outNr]
        fldValue = $inNr
        printf "%s%s", fldValue, (outNr<numOutFlds ? OFS : ORS)
    }
}

$ awk -v bash_arr_val='col1 col2 col3 col4' -f tst.awk file
col1 col2 col3 col4
val13 val1 val5 val9
val14 val2 val6 val10
val15 val3 val7 val11
val16 val4 val8 val12
$cat tst.awk
开始{
numOutFlds=拆分(bash_arr_val,outNr2name)

对于(outNr=1;outNr这不是最终解决方案,而是采购订单代码的改进,其中列顺序不是硬编码的:

#!/bin/bash

col_order=$1

awk -v col_order_string="$col_order" -v OFS='\t' '
  BEGIN {
    split(col_order_string, col_order, ",");
  }
  NR == 1 {
    for (i=1; i<=NF; i++) {
      f[$i] = i
    }
  }
  {
    s = ""
    for (i=1; i <= NF; i++) {
      printf "%s%s", s, $(f[col_order[i]]);
      s = OFS
    }
    printf "\n"
  }
' data.txt

欢迎来到SO,on SO,我们鼓励用户添加他们为解决自己的问题所付出的努力,所以请添加同样的努力,然后让我们知道。awk是您在这里的朋友。wrt
我有一个数组
-一个shell数组还是一个awk数组?@EdMorton shell数组。尝试有意义的数组名称,比
a更好
b,
,等等!FWIW当我为刚从一个值映射到另一个值的数组命名时,我尝试根据映射的内容来命名它们。例如
array[]
将输出字段号映射到字段名,所以我将其命名为
outNr2name[]
,然后
array_,并将_bash_值作为_索引[]
将字段名称映射到输出字段编号,因此我将其命名为
name2outNr[]
实际数组
将输出字段编号映射到输入字段编号,因此它将是
outnr2inr[]
。然后当您编写类似
outnr2inr[name2outNr[$I]的语句时=i
实际数组[array\u with_bash\u values\u as_index[$i]]=i
相比,你所做的事情一眼就清楚多了。
printf(“%s%s”,$(outNr2inNr[i]),i==NF ORS:OFS)
vs
printf(“%s%s”,$actual\u数组[i],i==NF ORS:OFS)
如果你为了锦上添花而使用变量名,比如
outNr
inNr
而不是
i
,并在循环内部设置/使用一个临时变量
fldName
而不是直接使用
$i
,那么一切都会变得非常清晰。@EdMorton,是的,先生;我正在学习它,威尔尝试进一步改进,先生。您介意我编辑您的答案,以显示我将如何使用这些名称编写脚本吗?您可以再次删除它,或者以后对它执行任何您喜欢的操作。@EdMorton,当您编辑我的答案时,我会介意的?“这永远不会发生,先生”,请随时随意编辑,先生,请执行。
$ cat tst.awk
BEGIN{
    numOutFlds = split(bash_arr_val,outNr2name)
    for ( outNr=1; outNr<=numOutFlds; outNr++ ) {
        name2outNr[outNr2name[outNr]] = outNr
    }
}

FNR==1 {
    for ( inNr=1; inNr<=NF; inNr++ ) {
        f[name2outNr[$inNr]] = inNr
    }
}
{
    for ( outNr=1; outNr<=numOutFlds; outNr++ ) {
        printf "%s%s", $(f[outNr]), (outNr<numOutFlds ? OFS : ORS)
    }
}

$ awk -v bash_arr_val='col1 col2 col3 col4' -f tst.awk file
col1 col2 col3 col4
val13 val1 val5 val9
val14 val2 val6 val10
val15 val3 val7 val11
val16 val4 val8 val12
#!/bin/bash

col_order=$1

awk -v col_order_string="$col_order" -v OFS='\t' '
  BEGIN {
    split(col_order_string, col_order, ",");
  }
  NR == 1 {
    for (i=1; i<=NF; i++) {
      f[$i] = i
    }
  }
  {
    s = ""
    for (i=1; i <= NF; i++) {
      printf "%s%s", s, $(f[col_order[i]]);
      s = OFS
    }
    printf "\n"
  }
' data.txt
./script 'col1,col2,col3,col4'