如何按倒数第二个字段对具有可变数量字段的输入进行排序?
How do I sort input with a variable number of fields by the second-to-last field?
编者注:原题题中提到tabs作为字段分隔符
在文本中,例如
500 east 23rd avenue Toronto 2 890 400000 1
900 west yellovillage blvd Mississauga 3 800 600090 3
您将如何按倒数第二列的升序排序?
编者注:OP 后来提供了另一个示例输入行,500 Jackson Blvd Toronto 3 700 40000 2
,其中仅包含 8 空格分隔的输入字段(与9),表明需要处理输入中的变量字段数。
我建议查看 "man sort"。
您将了解如何指定字段分隔符以及如何指定应用作排序键的字段索引。
您可以使用 sort -k 2
例如:
echo -e '000 west \n500 east\n500 east\n900 west' | sort -k 2
结果是:
500 east
500 east
900 west
000 west
您可以在 sort 的手册页中找到更多信息。查看手册页的末尾。在作者之前你有一些有趣的信息:)
再见
注意:有几个可能独立的问题:
更新:问题C是相关的。
问题 A: 正如问题标题所暗示的那样 仅:如何使用制表符 (\t
) 作为字段分隔符?
问题 B: 给定一个 fixed字段数?
问题 C: 给定一个 变量字段数?
问题A的答案:
sort
的 -t
选项允许您指定字段分隔符。
默认情况下,sort
使用 运行 个 line-interior 空格作为分隔符。
假设 Bash、Ksh 或 Zsh,您可以使用 ANSI C-quoted string ($'...'
) 指定单个制表符作为字段分隔符 ($'\t'
):
sort -t $'\t' -n -k8,8 file # -n sorts numerically; omit for lexical sorting
问题B的答案:
注意:这假设所有输入行都具有 相同的 字段数,并且输入来自文件 file
:
# Determine the index of the next-to-last column, based on the first
# line, using Awk:
nextToLastColNdx=$(head -n 1 file | awk -F '\t' '{ print NF - 1 }')
# Sort numerically by the next-to-last column (omit -n to sort lexically):
sort -t $'\t' -n -k$nextToLastColNdx,$nextToLastColNdx file
注意:要按 单个 字段排序,请始终将其指定为 end 字段(例如,-k8,8
), 如上所述,因为 sort
,仅给定一个 start 字段索引(例如,-k8
),从指定字段 到行的剩余部分.
问题C的答案:
注意:这假设输入行可能有可变个字段,并且在每一行上该行的second-to-last 作为排序字段的字段;输入来自文件 file
:
awk '{ printf "%s\t%s\n", $(NF-1), [=12=] }' file |
sort -n -k1,1 | # omit -n to perform lexical sorting
cut -f2-
awk
命令提取每行的 second-to-last 字段并 将其添加到 输出的输入行,由制表符分隔。
- 结果按第一个字段排序(即每个输入行的 second-to-last 字段)。
- 最后,再次删除人为前置的排序字段,使用
cut
。
编者注:原题题中提到tabs作为字段分隔符
在文本中,例如
500 east 23rd avenue Toronto 2 890 400000 1
900 west yellovillage blvd Mississauga 3 800 600090 3
您将如何按倒数第二列的升序排序?
编者注:OP 后来提供了另一个示例输入行,500 Jackson Blvd Toronto 3 700 40000 2
,其中仅包含 8 空格分隔的输入字段(与9),表明需要处理输入中的变量字段数。
我建议查看 "man sort"。
您将了解如何指定字段分隔符以及如何指定应用作排序键的字段索引。
您可以使用 sort -k 2
例如:
echo -e '000 west \n500 east\n500 east\n900 west' | sort -k 2
结果是:
500 east
500 east
900 west
000 west
您可以在 sort 的手册页中找到更多信息。查看手册页的末尾。在作者之前你有一些有趣的信息:)
再见
注意:有几个可能独立的问题:
更新:问题C是相关的。
问题 A: 正如问题标题所暗示的那样 仅:如何使用制表符 (
\t
) 作为字段分隔符?问题 B: 给定一个 fixed字段数?
问题 C: 给定一个 变量字段数?
问题A的答案:
sort
的 -t
选项允许您指定字段分隔符。
默认情况下,sort
使用 运行 个 line-interior 空格作为分隔符。
假设 Bash、Ksh 或 Zsh,您可以使用 ANSI C-quoted string ($'...'
) 指定单个制表符作为字段分隔符 ($'\t'
):
sort -t $'\t' -n -k8,8 file # -n sorts numerically; omit for lexical sorting
问题B的答案:
注意:这假设所有输入行都具有 相同的 字段数,并且输入来自文件 file
:
# Determine the index of the next-to-last column, based on the first
# line, using Awk:
nextToLastColNdx=$(head -n 1 file | awk -F '\t' '{ print NF - 1 }')
# Sort numerically by the next-to-last column (omit -n to sort lexically):
sort -t $'\t' -n -k$nextToLastColNdx,$nextToLastColNdx file
注意:要按 单个 字段排序,请始终将其指定为 end 字段(例如,-k8,8
), 如上所述,因为 sort
,仅给定一个 start 字段索引(例如,-k8
),从指定字段 到行的剩余部分.
问题C的答案:
注意:这假设输入行可能有可变个字段,并且在每一行上该行的second-to-last 作为排序字段的字段;输入来自文件 file
:
awk '{ printf "%s\t%s\n", $(NF-1), [=12=] }' file |
sort -n -k1,1 | # omit -n to perform lexical sorting
cut -f2-
awk
命令提取每行的 second-to-last 字段并 将其添加到 输出的输入行,由制表符分隔。- 结果按第一个字段排序(即每个输入行的 second-to-last 字段)。
- 最后,再次删除人为前置的排序字段,使用
cut
。