输入:
$ cat a.txt
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
$
输出:
$ cat a.txt | sort SOMEMAGIC
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
$
问题:如果我有几个字符长的分隔符,我该如何排序? (“FOO”)?
在示例中a.txt
按第二列排序。
问题是一般来说,数字a.txt
可以是任何东西。
答案1
使用egsed
将字符串替换为单字符分隔符,按列排序,然后再次替换回分隔符:
sed -e s/FOO/X/g a.txt | sort -k 2,2 -t X | sed -e s/X/FOO/g
这假设您知道有一个字符未出现在输入中。控制字符是常见的候选字符,但您需要根据您对输入格式的了解做出选择。
答案2
尝试这个:
$ perl -ane '
push @h,[$_,(split(/FOO/))[1]];
END {
print map { $_->[0] }
sort {$a->[1] <=> $b->[1]}
@h;
}
' file
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
解释
将每个数组 ref [line, key] 存储在 array 中
@h
:[$_,(split(/FOO/))[1]]
当完成读取文件时:
@h
按键对数组中的数组引用进行排序sort {$a->[1] <=> $b->[1]}
- 从中提取原始行
@h
并打印map { $_->[0] }
答案3
假设您的字段是数字,GNUsort
的版本排序可能有帮助。将分隔符设置为F
,以便尾部OO
fromFOO
进入字段 2 并且字段 2 被视为sort
包含 value OO2, OO5 and OO1
。在字段 2 上指定版本排序可确保忽略非数字前缀OO
,并且输出按字段 2 的尾随数字部分排序
sort -k2,2V -t 'F' a.txt
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
或者使用 GNU awk
,如果您可以忍受内存中解决方案的开销:
awk -F'FOO' '{a[$2]=$0};END{asort(a, b, "@ind_num_asc");
for (i in b) print b[i]}' a.txt
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
答案4
我认为您不必过多关注分隔符,而应该关注sort -k
眼睛。您可以为键指定字符范围。
info sort
...给定输入行“foo bar”,
sort
将其分成字段“foo”和“bar”。字段分隔符不被认为是前面字段或后面字段的一部分,因此使用“sort -t”“”,同一输入行具有三个字段:空字段、“foo”和“bar”。但是,延伸到行尾的字段(如“-k 2”)或由范围组成的字段(如“-k 2,3”), 保留范围端点之间存在的字段分隔符。
正如 Stephane 所评论的那样,反之亦然 - 您可以仅对具有字节范围的字段的切片进行排序,甚至可以对具有多个键的同一字段的多个切片进行排序。因此,在您的情况下,您可以多次使用具有不同范围的同一字段。看?
sort -k1.5n -k1.1n --debug <<\DATA
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
DATA
sort: using simple byte comparison
sort: leading blanks are significant in key 1; consider also specifying 'b'
sort: key 1 is numeric and spans multiple fields
sort: key 2 is numeric and spans multiple fields
2FOO1FOO9
_
_
_________
1FOO2FOO3
_
_
_________
4FOO5FOO5
_
_
_________
这指示sort
对主键进行排序,从字段 1 中的第 5 个字节开始,一直延伸到字段 1 的末尾,然后从字段 1 中的第 1 个字节到字段 1 的末尾进行排序。正如我希望上面所展示的那样,该--debug
选项在尝试排序时非常有用。sort
但这里是没有调试的:
sort -k1.5n -k1.1n <<\DATA
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
DATA
###OUTPUT###
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
如果您只想sort
为每个字符使用一个字符,则需要缩小范围。在上面的示例中,-k1.5n
从字节 5 到字段结束工作,因为关键规范的工作方式如下:
-k[begin field].[first byte in key],[end field].[last byte in key]
因此,虽然这种情况的结果是相同的,但您可以在打开它的同一字节上关闭每个字段范围,如下所示:
sort -k1.5,1.5n -k1.1,1.1n
因此sort
每个密钥仅由一个字节组成。