基于文件上的十六进制对一些模式匹配行进行排序

时间:2018-02-18 23:47:06

标签: bash sorting awk sed hex

我有一个名为stuff.txt的文件包含:

#Some text
##More text
blahblahblah
TAG["1AF450"]
TAG["002B4C"]
TAG["FFF250"]
TAG["6D50BB"]
more text...
#blehblehbleh

我想根据文件的十六进制值在文件中仅排序包含TAG的行。期望的输出:

#Some text
##More text
blahblahblah
TAG["002B4C"]
TAG["1AF450"]
TAG["6D50BB"]
TAG["FFF250"]
more text...
#blehblehbleh

如何实现这一目标?感谢。

5 个答案:

答案 0 :(得分:2)

我假设十六进制数字总是长6个大写字符。

使用GNU awk:

awk '/^TAG\["[[:xdigit:]]{6}"]$/ { a[i++]=$0; next }
     a[0] {
         asort(a);
         for (j=1;j<=i;j++) { print a[j] }
         delete a;
         i=0
     }1' file

注意:如果文件最终以多个TAG记录结束,则必须在脚本末尾添加:

END{
    asort(a);
    for (j=1;j<=i;j++) { print a[j] }
}

答案 1 :(得分:1)

Perl救援!

perl -ne 'if (/TAG\[".*"\]/){
              push @t, $_;
          } elsif (@t) {
              print for map qq(TAG["$_"]\n),
                        sort { hex $a <=> hex $b }
                        map /(?<=").+(?=")/g, @t;
              @t = ();
              print;
          } else { print }' -- stuff.txt
  • -n逐行读取输入行
  • 如果该行与正则表达式匹配,即它包含TAG [“...”],则将其推送到数组@t
  • 否则,如果已经填充了@t,则按十六进制值排序并打印; @t被清空所以不会再打印
  • 否则,我们在第一个TAG之前或者我们已经打印过了,所以我们打印了这条线。

如果十六进制值的长度都相同(小数字的开头为0),则可以简化排序

print for sort @t;

答案 2 :(得分:1)

awk救援!

$ awk '/^TAG/{print | "sort"; next} 1' file

#Some text
##More text
blahblahblah
TAG["002B4C"]
TAG["1AF450"]
TAG["6D50BB"]
TAG["FFF250"]
more text...
#blehblehbleh

NB。,因为您的记录具有固定的结构,因此无需提取十六进制值,因为行的词法排序将具有相同的排序顺序。

答案 3 :(得分:1)

这可能适合你(GNU csplit,sort&amp; bash):

csplit file '/^TAG/' '/^[^T]/' && cat xx00 <(sort xx01) xx02 > file && rm xx??

将文件拆分为3个部分,将头部,已排序的中间和尾部连接回原始文件,并删除csplit创建的所有工作文件。

答案 4 :(得分:1)

假设所有标签的长度相同,这就是如何可靠地完成此工作的方法:

$ awk -v OFS='\t' '!(/^TAG/ && p~/^TAG/){c++} {print c, $0; p=$0}' file | sort -k1,1n -k2 | cut -f2-
#Some text
##More text
blahblahblah
TAG["002B4C"]
TAG["1AF450"]
TAG["6D50BB"]
TAG["FFF250"]
more text...
#blehblehbleh