我们说我有一个包含多个列的文件,我想获得几个字段,但它们可能没有按顺序增加。字段索引在数组中,索引可以是任何顺序或根本不是顺序,索引的数量是未知的,例如:
arr=(1 3 2) #indexes, unknown length
echo 'c1 c2 c3' | cut -d " " -f "${arr[*]}"
输出是
c1 c2 c3
但我想要
c1 c3 c2
所以似乎cut
在阅读之前对字段进行排序,我不想这样做。我不限于cut
,可以使用任何其他命令。
但是,我只限于这个相当旧版本的bash:
GNU bash, version 2.05b.0(1)-release (i586-suse-linux)
Copyright (C) 2002 Free Software Foundation, Inc.
编辑解答感谢Benjamin W和Glenn Jackman
echo "1 2 3" | awk -v fields="${arr[*]}" 'BEGIN{ n = split(fields,f) } { for (i=1; i<=n; ++i) printf "%s%s", $f[i], (i<n?OFS:ORS) }'
使用&#39; *&#39;引用数组非常重要。而不是&#39; @&#39;。
答案 0 :(得分:1)
这可能适用于bash 2.05,也可能不适用:
arr=(1 3 2)
set -f # disable filename generation
while read line; do
set -- $line # unquoted: taking advantage of word splitting,
# store the words as positional parameters
for i in "${arr[@]}"; do
printf "%s " "${!i}" # indirect variable expansion
done
echo
done < file
或者,perl
$ cat file
c1 c2 c3
$ perl -slane '
BEGIN {@a = map {$_ - 1} split " ", $arr}
print join " ", @F[@a]
' -- -arr="${arr[*]}" file
c1 c3 c2
答案 1 :(得分:1)
使用awk
$ arr=(1 3 2)
$ echo 'c1 c2 c3' | awk -v arr="${arr[*]}" '
BEGIN {
split(arr, idx," ");
}
{
for(i=1; i<=length(idx); ++i)
printf("%s ",$idx[i])} ;
END {
printf("\n")
}
'
arr
拆分为' '
并分配给idx i
答案 2 :(得分:0)
使用FreeASlot
:
GeneralParkingLot
顺序由命令行传递的DowntownParkingLot
变量给出。假设此变量包含输入文件中可用的空格分隔值。
在awk
块中,数组$ cat file
a b c d
a b c d
a b c d
a b c d
$ awk -v ord="1 4 3 2" 'BEGIN { split(ord, order, " ") }
{
split($0, line, FS)
for (i = 1; i <= length(order); ++i)
$i = line[order[i]]
print
}' file
a d c b
a d c b
a d c b
a d c b
是通过在空格上拆分而从ord
创建的。
在默认块中,当前输入行被分割为BEGIN
上的数组order
(默认为空白)。然后根据ord
数组重新排列字段,然后打印出重新构建的行。
没有测试line
中的传入值是否合理。如果输入具有 N 列,则必须包含从1到 N 的所有整数。
答案 3 :(得分:0)
从您的印刷品中提取您的读物,以便您可以命名零件并相应地订购。
$: cat x
c1 c2 c3
c1 c2 c3
c1 c2 c3
c1 c2 c3
c1 c2 c3
$: cut -f 1,3,2 x |
> while read a b c
> do printf "$a $c $b\n"
> done
c1 c3 c2
c1 c3 c2
c1 c3 c2
c1 c3 c2
c1 c3 c2
这会将读取循环放入bash解释器,它不像二进制文件那么快,但不需要您已经使用的其他工具。
如果你有perl,我没有看到使用awk的重点,所以如果文件足够大你需要更快的解决方案,试试这个:
perl -a -n -e 'print join " ", @F[0,2,1],"\n"' x
假设很多,并在换行前添加一个空格,但应该给你一个工作的地方开始。