在 linux bash 中反转文件行顺序但对于块每 3 行
In linux bash reverse file lines order but for blocks each 3 lines
我想反转一个文件,但是在这个文件中我每行记录了 3 行
a1
a2
a3
...
x1
x2
x3
我想要这样的文件
x1
x2
x3
...
a1
a2
a3
我使用 Linux,所以 tail -r
对我不起作用。
这太丑了,我什至有点羞于 post 它...所以我想我会在出现更合适的答案后立即删除它。
tac /path/to/file | awk '{ a[(NR-1)%3]=[=10=]; if (NR%3==0) { print a[2] "\n" a[1] "\n" a[0] }}'
随着文件:
~$ cat f
1
2
3
4
5
6
7
8
9
with awk:将第一行存储在 a
中,然后将每一行附加到 a
和第三行 print/reinitialise:
~$ awk '{a=[=11=]"\n"a}NR%3==0{print a}NR%3==1{a=[=11=]}' f
3
2
1
6
5
4
9
8
7
然后再次使用tac反转:
~$ awk '{a=[=12=]"\n"a}NR%3==0{print a}NR%3==1{a=[=12=]}' f | tac
7
8
9
4
5
6
1
2
3
您可以在 awk 中使用关联数组完成所有这些操作:
BEGIN { j=1 }
++i>3 { i=1; ++j }
{ a[j,i]=[=10=] }
END{ for(m=j;m>0;--m)
for(n=1;n<=3;++n) print a[m,n]
}
运行 像这样:
awk -f script.awk file.txt
或者当然,如果您更喜欢单线,您可以使用这个:
awk 'BEGIN{j=1}++i>3{i=1;++j}{a[j,i]=[=12=]}END{for(m=j;m>0;--m)for(n=1;n<=3;++n)print a[m,n]}' file.txt
说明
这使用两个计数器:i
从 1 运行到 3 和 j
,它计算 3 行的组数。所有行都存储在关联数组 a
中,并在 END
块中反向打印。
正在测试
$ cat file
a1
a2
a3
b1
b2
b3
x1
x2
x3
$ awk 'BEGIN{j=1}++i>3{i=1;++j}{a[j,i]=[=13=]}END{for(m=j;m>0;--m)for(n=1;n<=3;++n)print a[m,n]}' file
x1
x2
x3
b1
b2
b3
a1
a2
a3
awk 的另一种方式
awk '{a[i]=a[i+=(NR%3==1)]?a[i]"\n"[=10=]:[=10=]}END{for(i=NR/3;i>0;i--)print a[i]}' file
输入
a1
a2
a3
x1
x2
x3
b1
b2
b3
输出
b1
b2
b3
x1
x2
x3
a1
a2
a3
这里有一个纯Bash(Bash≥4)的可能性,对于不太大的文件应该没问题。
我们还假设您文件中的行数是 3 的倍数。
mapfile -t ary < /path/to/file
for((i=3*(${#ary[@]}/3-1);i>=0;i-=3)); do
printf '%s\n' "${ary[@]:i:3}"
done
我想反转一个文件,但是在这个文件中我每行记录了 3 行
a1
a2
a3
...
x1
x2
x3
我想要这样的文件
x1
x2
x3
...
a1
a2
a3
我使用 Linux,所以 tail -r
对我不起作用。
这太丑了,我什至有点羞于 post 它...所以我想我会在出现更合适的答案后立即删除它。
tac /path/to/file | awk '{ a[(NR-1)%3]=[=10=]; if (NR%3==0) { print a[2] "\n" a[1] "\n" a[0] }}'
随着文件:
~$ cat f
1
2
3
4
5
6
7
8
9
with awk:将第一行存储在 a
中,然后将每一行附加到 a
和第三行 print/reinitialise:
~$ awk '{a=[=11=]"\n"a}NR%3==0{print a}NR%3==1{a=[=11=]}' f
3
2
1
6
5
4
9
8
7
然后再次使用tac反转:
~$ awk '{a=[=12=]"\n"a}NR%3==0{print a}NR%3==1{a=[=12=]}' f | tac
7
8
9
4
5
6
1
2
3
您可以在 awk 中使用关联数组完成所有这些操作:
BEGIN { j=1 }
++i>3 { i=1; ++j }
{ a[j,i]=[=10=] }
END{ for(m=j;m>0;--m)
for(n=1;n<=3;++n) print a[m,n]
}
运行 像这样:
awk -f script.awk file.txt
或者当然,如果您更喜欢单线,您可以使用这个:
awk 'BEGIN{j=1}++i>3{i=1;++j}{a[j,i]=[=12=]}END{for(m=j;m>0;--m)for(n=1;n<=3;++n)print a[m,n]}' file.txt
说明
这使用两个计数器:i
从 1 运行到 3 和 j
,它计算 3 行的组数。所有行都存储在关联数组 a
中,并在 END
块中反向打印。
正在测试
$ cat file
a1
a2
a3
b1
b2
b3
x1
x2
x3
$ awk 'BEGIN{j=1}++i>3{i=1;++j}{a[j,i]=[=13=]}END{for(m=j;m>0;--m)for(n=1;n<=3;++n)print a[m,n]}' file
x1
x2
x3
b1
b2
b3
a1
a2
a3
awk 的另一种方式
awk '{a[i]=a[i+=(NR%3==1)]?a[i]"\n"[=10=]:[=10=]}END{for(i=NR/3;i>0;i--)print a[i]}' file
输入
a1
a2
a3
x1
x2
x3
b1
b2
b3
输出
b1
b2
b3
x1
x2
x3
a1
a2
a3
这里有一个纯Bash(Bash≥4)的可能性,对于不太大的文件应该没问题。 我们还假设您文件中的行数是 3 的倍数。
mapfile -t ary < /path/to/file
for((i=3*(${#ary[@]}/3-1);i>=0;i-=3)); do
printf '%s\n' "${ary[@]:i:3}"
done