我有以下元素列表:
a, b, c, 1337, d, e
我希望我有:
e, d, 1337, c, b, a
我怎样才能在 bash 中实现这一点?
你可以这样做awk
:
#!/bin/bash
awk 'BEGIN{FS=",[ ]*"; OFS=", "}
{
for (i=NF; i>0; i--) {
printf "%s", $i;
if (i>1) {
printf "%s", OFS;
}
}
printf "\n"
}'
脚本解释:
FS=",[ ]*";
:字段分隔符(输入的分隔符)的正则表达式匹配逗号,后跟零个或多个空格,因此您的输入可以是以下任何一种:
a, b, c, 1337, d, e
a,b,c,1337,d,e
a, (many spaces) b, c,1337,d, e
OFS=", "
:输出字段分隔符(输出的分隔符)将明确地是一个逗号后跟一个空格(因此输出看起来一致)for (i=NF; i>0; i--) { ... }
:NF
表示当前行的字段数。这里我们向后迭代,从最后一个字段打印到第一个字段。if (i>1) { ... }
:仅打印OFS
如果它不是输出中的最后一个字段printf "\n"
: 新队。示例用法:
$ ./script_name < input_file > output_file
如果您的输入很简单,并且列数是静态的,那么您总是可以使用硬编码的awk
解决方案:
awk -F, '{ print $6", "$5", "$4", "$3", "$2", "$1 }'
这假设您有 6 列用逗号分隔。如果您有“逗号 + 空格”分隔符,,
则可以使用.-F', '
而不是-F,
.
带有输出的简单示例用法:
$ echo "a, b, c, 1337, d, e" | awk -F', ' '{ print $6", "$5", "$4", "$3", "$2", "$1 }'
e, d, 1337, c, b, a
使用文件作为输入:
awk -F', ' '{ print $6", "$5", "$4", "$3", "$2", "$1 }' your_file
然后,您可以通过附加将输出从该文件重定向到另一个文件> reversed_columns
;在这种情况下,“reversed_columns”是新文件的名称。
这个解决方案不是很优雅,但应该适用于任意数量的字段:
sed 's/, /\n/g' | tac | sed ':a;$!{N;ba};s/\n/, /g'
要么通过管道将数据传递给它,要么将文件作为第二个参数提供给 first sed
(不过,它会将整个文件打印为一个逗号分隔的行)。
$ awk -F", " '{for (i=NF;i;i--) printf "%s ",$i; print ""}' < datafile
e d 1337 c b a
使用以下脚本,列表中有多少元素并不重要:
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
此外,您可以使用以下 perl one-liner(它会\n
在第一个元素之后添加一个)
echo "a, b, c, 1337, d, e" | perl -ne 'foreach(reverse(split(", ",$_))){print "$_, "}'
重击:
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
)
我使用括号来创建一个子shell,因此我不会更改当前shell 中的IFS 变量。