简体   繁体   English

bash逗号分隔值的反向顺序

[英]bash reverse order of comma separated values

I've got the following list of elements: 我有以下元素列表:

a, b, c, 1337, d, e

I wish I have: 我希望我有:

e, d, 1337, c, b, a

How can I achieve that in bash? 我怎样才能在bash中实现这一目标?

You can do this with awk : 你可以用awk做到这一点:

#!/bin/bash

awk 'BEGIN{FS=",[ ]*"; OFS=", "}
    {
        for (i=NF; i>0; i--) {
            printf "%s", $i;
            if (i>1) {
                printf "%s", OFS;
            }
        }
        printf "\n"
    }'

Explanation of the script: 脚本说明

  • FS=",[ ]*"; : The regex for Field Separator (delimiter for your input) matches a comma followed by zero or more spaces, so your input can be any of: Field Separator的正则表达式(输入的分隔符)与逗号后跟零个或多个空格匹配,因此您的输入可以是以下任何一个:
    • a, b, c, 1337, d, e
    • a,b,c,1337,d,e
    • a, (many spaces) b, c,1337,d, e
  • OFS=", " : The Output Field Separator (delimiter for your output) will be explicitly a comma followed by a space (so output looks consistent) OFS=", "输出字段分隔符输出的分隔符)将显式为逗号,后跟空格(因此输出看起来一致)
  • for (i=NF; i>0; i--) { ... } : NF means the Number of Fields in the current line. for (i=NF; i>0; i--) { ... }NF表示当前行中的字段数 Here we iterate backwards, printing from the last field to the first field. 在这里,我们向后迭代,从最后一个字段打印到第一个字段。
  • if (i>1) { ... } : Only print the OFS if it's not the last field in the output if (i>1) { ... } :如果OFS不是输出中的最后一个字段,则仅打印OFS
  • printf "\\n" : new line. printf "\\n" :新行。

Sample usage : 样品用法

$ ./script_name < input_file > output_file

This solution is not very elegant, but should work with any number of fields: 这个解决方案不是很优雅,但应该适用于任意数量的字段:

sed 's/, /\n/g' | tac | sed ':a;$!{N;ba};s/\n/, /g'

Either pipe you data to it or give a file as second argument to first sed (it will print the whole file as one comma-separated line, though). 要么将数据传输给它,要么将文件作为第一个sed第二个参数(它将整个文件打印为一个以逗号分隔的行)。

If your input is simple, and the number of columns is static, you could always go with a hardcoded awk solution: 如果您的输入很简单,并且列数是静态的,您可以随时使用硬编码的awk解决方案:

awk -F, '{ print $6", "$5", "$4", "$3", "$2", "$1 }'

This assumes that you have 6 columns that are separated by a comma. 这假设您有6个用逗号分隔的列。 If you have a "comma + space" delimiter, , , you can use -F', ' instead of just -F, . 如果你有一个“逗号+空格”分隔符,你可以使用-F', '而不只是-F,

A straightforward example usage with output: 输出的简单示例用法:

$ echo "a, b, c, 1337, d, e" | awk -F', ' '{ print $6", "$5", "$4", "$3", "$2", "$1 }'
e, d, 1337, c, b, a

With a file as input: 使用文件作为输入:

awk -F', ' '{ print $6", "$5", "$4", "$3", "$2", "$1 }' your_file

You can then redirect the output from that to another file by appending > reversed_columns ; 然后,您可以通过附加> reversed_columns将输出重定向到另一个文件; "reversed_columns" being the name of the new file in this case. “reversed_columns”是这种情况下新文件的名称。

With the following script, it doesn't matter how many elements are in the list: 使用以下脚本,列表中有多少元素无关紧要:

IFS=', '; read -a array <<< "a, b, c, 1337, d, e"
let i=${#array[@]}-1; 
while [ $i -ge 0 ]; do 
    echo -n "${array[$i]}, "; 
    let i--; 
done

Also, you can use the following perl one-liner (it will add a \\n after the first element though) 此外,您可以使用以下perl one-liner(它会在第一个元素之后添加\\n

echo "a, b, c, 1337, d, e" | perl -ne 'foreach(reverse(split(", ",$_))){print "$_, "}'
$ awk -F", " '{for (i=NF;i;i--) printf "%s ",$i; print ""}' < datafile
e d 1337 c b a 

bash: 庆典:

echo "a, b, c, 1337, d, e" | (
  IFS=", "
  while read line; do
    set -- $line
    for (( i=$#; i > 1; i-- )); do
      printf "%s, " "${!i}"
    done
    echo "$1"
  done
)

I use parentheses to create a subshell so I don't alter the IFS variable in the current shell. 我使用括号创建子shell,所以我不改变当前shell中的IFS变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM