如何按字母顺序对字段名称(而不是值)进行排序并在 bash 中基于它创建一个新文件

How to sort fields names(not values) in alphabetic manner and create a new file based on it in bash

我有一个包含 space 分隔字段及其值的文件。我想根据字段的字母顺序对该文件进行排序。

v_party_id="49529957" v_party_default_status_cd="NOTDFLT" v_src_system_id="VTX" v_pd_percent="0.0127" d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" 
v_party_id="49530058" v_party_default_status_cd="NOTDFLT" v_src_system_id="VTX" v_pd_percent="0.00285" d_report_ref_date="2021-03-31" v_accounting_standard="IFRS"

所有字段按字段名称(而非值)字母顺序排序后。 预期输出是-

d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_id="49529957" v_party_default_status_cd="NOTDFLT" v_src_system_id="VTX" v_pd_percent="0.0127" 
d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_id="49530058" v_party_default_status_cd="NOTDFLT" v_src_system_id="VTX" v_pd_percent="0.00285" 

我正在尝试通过 bash-

filecontent=( `cat "file1" `)
for t in "${filecontent[@]}"
do
        echo $t
done|sort

这让我输出为 -

d_report_ref_date="2021-03-31"
d_report_ref_date="2021-03-31"
v_accounting_standard="IFRS"
v_accounting_standard="IFRS"
v_party_default_status_cd="NOTDFLT"
v_party_default_status_cd="NOTDFLT"
v_party_id="49529957"
v_party_id="49530058"
v_pd_percent="0.00285"
v_pd_percent="0.0127"
v_src_system_id="VTX"
v_src_system_id="VTX"

如何获得所需的输出,即只有两行字段名已排序?

提前致谢!!!

假设值中没有空格,您应该可以使用以下内容:

# read a file line by line and split on spaces into an array
while IFS=' ' read -r -a elements; do
    # output array elements on separate lines, sort them and join with spaces
    printf "%s\n" "${elements[@]}" | sort | paste -sd' '
done < inputfile.txt

如果 "... ..." 之间有空格,您必须编写自己的解析器来标记该行。

您可以使用这个 gnu-awk 解决方案:

awk '
BEGIN {PROCINFO["sorted_in"] = "@val_str_asc"}
{
   for (i=1; i<=NF; ++i)
      a[i] = $i
   j = 0
   for (i in a)
      printf "%s", a[i] (++j<NF ? OFS : ORS)
}' file

d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49529957" v_pd_percent="0.0127" v_src_system_id="VTX"
d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49530058" v_pd_percent="0.00285" v_src_system_id="VTX"

Working Online Demo

详情:

  • PROCINFO["sorted_in"] = "@val_str_asc" 对值按字符串升序排列的数组进行排序
  • 第一个 for 循环将每个字段存储在数组 a 中,键作为字段位置,值作为字段值
  • 由于存在 PROCINFO 数组将按字母值顺序排序
  • 第二个 for 循环打印每个排序的条目

使用您显示的示例,请尝试执行以下 awk 命令。在 GNU awk.

中编写和测试
awk '
BEGIN {PROCINFO["sorted_in"] = "@val_str_asc"}
{
   split([=10=],a)
   j=0
   for (i in a){
      printf "%s", a[i] (++j<NF ? OFS : ORS)
   }
}'  Input_file

perl 将是对字段进行排序的不错选择:

perl -lane 'print "@{[sort @F]}"' file.txt

输出:

d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49529957" v_pd_percent="0.0127" v_src_system_id="VTX"
d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49530058" v_pd_percent="0.00285" v_src_system_id="VTX"

你已经有了一个很好的 GNU awk 解决方案,但如果你没有 GNU awk,那么在每个带有 decorate/sort/undecorate 习惯用法的 Unix 机器上的任何 shell 中使用任何 awk+sort:

$ awk '{for (i=1; i<=NF; i++) print NR, NF, $i}' file |
    sort -k1,1n -k3,3 |
    awk '{rec=rec sep ; sep=OFS} ++cnt=={print rec; rec=sep=cnt=""}'
d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49529957" v_pd_percent="0.0127" v_src_system_id="VTX"
d_report_ref_date="2021-03-31" v_accounting_standard="IFRS" v_party_default_status_cd="NOTDFLT" v_party_id="49530058" v_pd_percent="0.00285" v_src_system_id="VTX"