如何根据键名而不是它在 unix 中的位置对文件进行排序?
How to sort a file based on key name instead of its position in unix?
我想在 Unix 中对文件进行排序,为此我正在使用命令
sort file --field-separator=' ' --key=7,7
但是这个字段的位置不固定,有时可以是第7个字段,有时是第6个或第8个字段。
我们知道是否可以根据字段名称对文件进行排序,例如
sort file --field-separator=' ' --keyname=<my_unique_id>
文件看起来像这样,我想根据 party_id
排序
status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
sort
没有命名键的概念,但是你可以执行一个 Schwartzian transform 临时将键作为前缀添加到行中,在第一个字段上排序,然后丢弃它。
sed 's/\(.*\)\(party_id="[^"]*"\)/ /' file |
sort -t ' ' -k1,1 |
cut -f2-
(两个第一个后向引用之间和 sort -t
参数中的空格是文字制表符,但是 Stack Overflow 将其呈现为空格序列)。
使用 Decorate/Sort/Undecorate 习语并假设,就像在您提供的示例中一样,您引用的字符串不包含空格、=
或 "
:
装饰:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=10=]; next} }' file
36113477 status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
36053415 status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
装饰然后排序:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=11=]; next} }' file |
sort -k1,1n
36053415 status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
36113477 status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
装饰然后排序然后取消装饰:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=12=]; next} }' file |
sort -k1,1n |
cut -f2-
status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
使用GNU awk
(gawk
) 可以指定如何遍历数组。下面使用 party_id=XYZ
作为各自的索引将每一行保存在一个数组中,然后 returns 按所述索引排序的数组。对于非常大的文件,受 RAM 限制。
awk '{match([=10=],/party_id=[^ ]*/,[=10=],id) ; arr[id[0]]=[=10=]}
END {PROCINFO["sorted_in"]="@ind_str_asc"
for (i in arr) {print arr[i]}
}' infile.txt
我想在 Unix 中对文件进行排序,为此我正在使用命令
sort file --field-separator=' ' --key=7,7
但是这个字段的位置不固定,有时可以是第7个字段,有时是第6个或第8个字段。
我们知道是否可以根据字段名称对文件进行排序,例如
sort file --field-separator=' ' --keyname=<my_unique_id>
文件看起来像这样,我想根据 party_id
status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
sort
没有命名键的概念,但是你可以执行一个 Schwartzian transform 临时将键作为前缀添加到行中,在第一个字段上排序,然后丢弃它。
sed 's/\(.*\)\(party_id="[^"]*"\)/ /' file |
sort -t ' ' -k1,1 |
cut -f2-
(两个第一个后向引用之间和 sort -t
参数中的空格是文字制表符,但是 Stack Overflow 将其呈现为空格序列)。
使用 Decorate/Sort/Undecorate 习语并假设,就像在您提供的示例中一样,您引用的字符串不包含空格、=
或 "
:
装饰:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=10=]; next} }' file
36113477 status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
36053415 status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
装饰然后排序:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=11=]; next} }' file |
sort -k1,1n
36053415 status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
36113477 status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
装饰然后排序然后取消装饰:
$ awk -F'[ ="]+' -v OFS='\t' -v keyname='party_id' '{for (i=1; i<NF; i+=2) if ($i == keyname) { print $(i+1), [=12=]; next} }' file |
sort -k1,1n |
cut -f2-
status_date="2002-12-31" ref_date="2021-03-31" ead_percent="1" accounting_standard="IFRS" orig_src_system_id="GRD" party_default_status_cd="UNLIKE" party_id="36053415" v_src_system_id="XYZ"
status_date="2000-01-31" ref_date="2021-03-31" ead_percent="0.00365316" accounting_standard="IFRS" party_default_status_cd="NOTDFLT" party_id="36113477" v_src_system_id="ABC"
使用GNU awk
(gawk
) 可以指定如何遍历数组。下面使用 party_id=XYZ
作为各自的索引将每一行保存在一个数组中,然后 returns 按所述索引排序的数组。对于非常大的文件,受 RAM 限制。
awk '{match([=10=],/party_id=[^ ]*/,[=10=],id) ; arr[id[0]]=[=10=]}
END {PROCINFO["sorted_in"]="@ind_str_asc"
for (i in arr) {print arr[i]}
}' infile.txt