有没有办法让Unix排序基于转义字符忽略分隔符?

时间:2017-07-05 20:47:21

标签: sorting unix

我想使用Unix排序但有时我想要字段分隔符,如果用一对封闭分隔符括起来不被视为字段分隔符。例如,让我们看一下基本情况,然后再看一下具体情况:

  

基本案例:

"xyz"|27
"abc"|15 
"xyz"|25

当我执行以下命令时:

  

sort -t' |' -k1,1 -k2,2n test1.txt

我得到了我想要的东西:

"abc"|15
"xyz"|25
"xyz"|27
  

现在让我们看看带有转义字符对的第二种情况<>提供:

"x<|>yz"|27
"abc"|15
"xyz"|25 

如果我运行相同的命令,我会得到一些我不想要的东西:

"abc"|15
"x<|>yz"|27
"xyz"|25

有没有告诉unix排序,如果&lt;&gt;或{}或()或甚至像(&lt;)这样的奇怪对,然后忽略封闭分隔符对内的实际字段分隔符?实际的字段分隔符将始终是管道。

我的目标是:

"abc"|15
"xyz"|25
"x<|>yz"|27

2 个答案:

答案 0 :(得分:0)

简短:sort没有这样做。

long:您可以通过对数据进行前/后过滤来解决此问题,以使字段在列中对齐。如果我只使用命令行sort,我会使用sed对文件进行预处理,以便分隔符为tab字符(在POSIX中,在任何可打印之前)字符)。排序后,用垂直条替换tab将是另一个sed - 命令。

对于&#34;主要是&#34;,主要的缺陷是在某些语言环境中,各种标点符号基本上都被忽略了。

答案 1 :(得分:0)

我不这么认为,但你可以:

  1. 复制密钥并清除<|>
  2. 上的副本
  3. 将原始密钥移至最后
  4. 对已清理的密钥进行排序
  5. 删除已清理的密钥并将原始密钥移回其位置
  6. 使用awk:

    $ awk 'BEGIN{FPAT="([^|]+|(\"[^\"]+\"))";OFS="|"}{i=$1;gsub(/<.*>/,"",i);print i,$2,$1}' file | sort -t\| -k1 -k2 | awk 'BEGIN{FPAT="([^|]+|(\"[^\"]+\"))";OFS="|"}{print $NF,$2}'
    "abc"|15
    "xyz"|25
    "x<|>yz"|27
    

    解释(1.和2.):

    $ awk 'BEGIN{FPAT="([^|]+|(\"[^\"]+\"))";OFS="|"}{i=$1;gsub(/<.*>/,"",i);print i,$2,$1}' file
    

    输出:

    "xyz"|27|"x<|>yz"
    "abc"|15|"abc"
    "xyz"|25|"xyz"
    

    代码解释:

    BEGIN { 
        FPAT="([^|]+|(\"[^\"]+\"))"  # define fields to allow field separators in quotes
        OFS="|"                      # output field separator to |
    }
    {
        i=$1                         # copy first field to var i
        gsub(/<.*>/,"",i)            # remove "escaped" part
        print i,$2,$1                # output 
    }
    

    管道到sort -t\| -k1 -k2输出(3.):

    "abc"|15|"abc"
    "xyz"|25|"xyz"
    "xyz"|27|"x<|>yz"
    

    代码解释:

    ...                               # see previous explanation
    {
        print $NF,$2                  # print last first then second (original order)
    }
    

    并且(4.)的结果就在那里。