【问题标题】:How to sort inside a cell captured by awk如何在 awk 捕获的单元格内进行排序
【发布时间】:2022-01-10 17:53:28
【问题描述】:

我有一个包含如下行的文件,其中第 3 列有多个需要排序的数值:

文件:h1.csv

S101-T1 类;3343-1-25310;3344-1-25446 3345-1-25691 3348-1-27681 3347-1-28453
S101-T2 类;3343-2-25310;3344-2-25446 3345-2-25691
S101-T1 类;3343-3-25310;3345-3-25691 3343-3-25314
S101-T2 类;3343-4-25310;3345-4-25691 3343-4-25314 3344-4-25314
S102-T1 类;3343-5-25310;3344-5-25446 3345-5-25691

所以,预期的输出是:

S101-T1 类;3343-1-25310;3344-1-25446 3345-1-25691 3347-1-28453 3348-1-27681
S101-T2 类;3343-2-25310;3344-2-25446 3345-2-25691
S101-T1 类;3343-3-25310;3343-3-25314 3345-3-25691
S101-T2 类;3343-4-25310;3343-4-25314 3344-4-25314 3345-4-25691
S102-T1 类;3343-5-25310;3344-5-25446 3345-5-25691

我的想法是用 awk 捕获第三列,然后对其进行排序,最后打印输出,但我只是为了捕获该列。我没有成功对其进行排序,也没有打印出不想要的输出。

这是我目前得到的代码...

cat h1.csv | awk -F';' '{ gsub(" ","\n",$3); print $0 }'

我已经尝试过(还有一些人给出了错误):

cat h1.csv | awk -F';' '{ gsub(" ","\n",$3); print $3 | "sort -u" }'
cat h1.csv | awk -F';' '{ gsub(" ","\n",$3); sort -u; print $3 }'

那么,有没有可能这样做,如何?,任何帮助!谢谢...

【问题讨论】:

  • 你为什么把一些数字放在粗体中?这有什么意义吗?
  • 是的,只是为了突出显示当前订单和所需订单
  • 这能回答你的问题吗? stackoverflow.com/questions/6438896/… 您可以使用----field-separator=, 来使用逗号作为字段分隔符。
  • 不正确的欺骗。这个问题完全不同。这是关于在每条记录内排序而不是跨文件排序。
  • 您的答案假定您要排序的字符串始终具有相同的长度,并且始终由 4digits-1digit-5digits 部分组成,因为这就是您在示例输入/输出中显示的内容。如果情况并非总是如此,那么edit 你的问题是用1000-2-1 1000-10-1 200-1-1 之类的情况来解决这个问题(并测试现有的答案),如果按数字和字母顺序排序,排序会非常不同。

标签: awk gsub


【解决方案1】:

一种选择可能是将第 3 列拆分为空格,然后使用 asort() 获取使用 gnu-awk 的值。

然后再次连接前 2 个字段和拆分和排序的字段。

awk '
BEGIN{FS=OFS=";"}
{
  n=split($3, a, " ")
  asort(a)
  res = $1 OFS $2 OFS
  for (i = 1; i <= n; i++) {
    res = res " " a[i]
  }
  print res
}' file

输出

Class S101-T1;3343-1-25310; 3344-1-25446 3345-1-25691 3347-1-28453 3348-1-27681
Class S101-T2;3343-2-25310; 3344-2-25446 3345-2-25691
Class S101-T1;3343-3-25310; 3343-3-25314 3345-3-25691
Class S101-T2;3343-4-25310; 3343-4-25314 3344-4-25314 3345-4-25691
Class S102-T1;3343-5-25310; 3344-5-25446 3345-5-25691

【讨论】:

  • 是的,我已经做到了,它也可以,你的代码可以放在一行吗?我试过了,但出现错误..
  • @AndrésChandía 这将是一行代码awk 'BEGIN{FS=OFS=";"}{n=split($3,a," ");asort(a);res=$1 OFS $2 OFS;for(i=1;i&lt;=n;i++){res=res" "a[i]}print res}' file
【解决方案2】:

在 GNU awk 中,使用您显示的示例,请尝试遵循 awk 代码。

awk '
BEGIN{
  FS=OFS=";"
  PROCINFO["sorted_in"] = "@val_num_asc"
}
{
  nf=val=""
  delete value
  num=split($NF,arr," ")
  for(i=1;i<=num;i++){
    split(arr[i],arr2,"-")
    value[arr2[1]]=arr[i]
  }
  for(i in value){
    nf=(nf?nf " ":"")value[i]
  }
  $NF=nf
}
1
'  Input_file

说明:为上述添加详细说明。

awk '                                     ##Starting awk program from here.
BEGIN{                                    ##Starting BEGIN section from here.
  FS=OFS=";"                              ##Setting FS, OFS as ; here.
  PROCINFO["sorted_in"] = "@val_num_asc"  ##Setting PROCINFO using sorted_in to make sure array values are sorted by values in ascending order only.
}
{
  nf=val=""                               ##Nullifying variables here.
  delete value                            ##Deleting value array here.
  num=split($NF,arr," ")                  ##Splitting last field into arr with separator as space here.
  for(i=1;i<=num;i++){                    ##Traversing through all elements of array arr.
    split(arr[i],arr2,"-")                ##Splitting first value of arr into arr2 by delimiter of - to make sure to get only first value eg: 3344, 3345 etc.
    value[arr2[1]]=arr[i]                 ##Assigning value array value to arr value with index of arr2 value whose index of 1st.
  }
  for(i in value){                        ##Traversing through array value here.
    nf=(nf?nf " ":"")value[i]             ##Concatenating all values to nf here.
  }
  $NF=nf                                  ##Assigning last field value to nf here.
}
1                                         ##printing edited/non-edited line here.
'  Input_file                             ##Mentioning Input_file name here.

【讨论】:

    【解决方案3】:

    将 GNU awk 用于sorted_in

    $ cat tst.awk
    BEGIN {
        FS = OFS = ";"
        PROCINFO["sorted_in"] = "@val_str_asc"
    }
    {
        split($3,a," ")
        sorted = ""
        for (i in a) {
            sorted = (sorted=="" ? "" : sorted " ") a[i]
        }
        $3 = sorted
        print
    }
    

    $ awk -f tst.awk file
    Class S101-T1;3343-1-25310;3344-1-25446 3345-1-25691 3347-1-28453 3348-1-27681
    Class S101-T2;3343-2-25310;3344-2-25446 3345-2-25691
    Class S101-T1;3343-3-25310;3343-3-25314 3345-3-25691
    Class S101-T2;3343-4-25310;3343-4-25314 3344-4-25314 3345-4-25691
    Class S102-T1;3343-5-25310;3344-5-25446 3345-5-25691
    

    请注意,这假定按字母排序,因此它会在200-1-1 之前对1000-1-1 进行排序。只要您要排序的字符串始终由相同长度的部分组成,即 4digits-1digit-5digits,它就可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-13
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多