我有一个名为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
如何实现这一目标?感谢。
答案 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
逐行读取输入行如果十六进制值的长度都相同(小数字的开头为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