我有一个文件,我们称之为“a.txt”,这个文件包含以下文本行
do to what
我想知道 SED 命令是什么来反转此文本的顺序以使其看起来像
what to do
我必须做某种附加吗?就像将 'do' 附加到 'to' 所以它看起来像
to ++ do(使用 ++ 只是为了清楚)
我有一个文件,我们称之为“a.txt”,这个文件包含以下文本行
do to what
我想知道 SED 命令是什么来反转此文本的顺序以使其看起来像
what to do
我必须做某种附加吗?就像将 'do' 附加到 'to' 所以它看起来像
to ++ do(使用 ++ 只是为了清楚)
我知道tac
可以做一些相关的事情
$ cat file
do to what
$ tac -s' ' file
what to do $
其中-s
定义了分隔符,默认情况下是换行符。
我awk
会这样做:
awk '{ for (i=NF; i>=1; i--) printf (i!=1) ? $i OFS : $i "\n" }' file.txt
结果:
what to do
编辑:
如果您需要单行“就地”修改文件,请尝试:
{ rm file.txt && awk '{ for (i=NF; i>=1; i--) printf (i!=1) ? $i OFS : $i "\n" }' > file.txt; } < file.txt
由于这个问题被标记为sed,我的第一个答案是:
首先(使用任意_
标记查看的空间,当a.txt
包含do to what
:
sed -e '
:a;
s/\([^_]*\) \([^ ]*\)/\2_\1/;
ta;
y/_/ /;
' a.txt
what to do
比,当a.txt
包含do to to what
:
sed -e '
:a;
s/^\(\|.* \)\([^+ ]\+\) \2\([+]*\)\(\| .*\)$/\1\2\3+\4/g;
ta;
:b;
s/\([^_]*\) \([^ ]*\)/\2_\1/;
tb;
y/_/ /;
' <<<'do to to to what'
what to++ do
+
每个被抑制的重复单词都有一个:
sed -e ':a;s/^\(\|.* \)\([^+ ]\+\) \2\([+]*\)\(\| .*\)$/\1\2\3+\4/g;ta;
:b;s/\([^_]*\) \([^ ]*\)/\2_\1/;tb;
y/_/ /;' <<<'do do to what what what what'
what+++ to do+
但是由于有很多人在寻找简单的bash解决方案,所以有一个简单的方法:
xargs < <(uniq <(tac <(tr \ \\n <<<'do do to what what what what')))
what to do
这可以写成:
tr \ \\n <<<'do do to what what what what' | tac | uniq | xargs
what to do
甚至使用一些bash脚本:
revcnt () {
local wrd cnt plut out="";
while read cnt wrd; do
printf -v plus %$((cnt-1))s;
out+=$wrd${plus// /+}\ ;
done < <(uniq -c <(tac <(tr \ \\n )));
echo $out
}
会做:
revcnt <<<'do do to what what what what'
what+++ to do+
revcnt() {
local out i;
for ((i=$#; i>0; i--))
do
[[ $out =~ ${!i}[+]*$ ]] && out+=+ || out+=\ ${!i};
done;
echo $out
}
其中提交的字符串必须作为参数提交:
revcnt do do to what what what what
what+++ to do+
或者,如果需要处理标准输入(或来自文件):
revcnt() {
local out i arr;
while read -a arr; do
out=""
for ((i=${#arr[@]}; i--; 1))
do
[[ $out =~ ${arr[i]}[+]*$ ]] && out+=+ || out+=\ ${arr[i]};
done;
echo $out;
done
}
所以你可以处理多行:
revcnt <<eof
do to what
do to to to what
do do to what what what what
eof
what to do
what to++ do
what+++ to do+
这可能对您有用(GNU sed):
sed -r 'G;:a;s/^\n//;t;s/^(\S+|\s+)(.*)\n/\2\n\1/;ta' file
解释:
G
在模式空间的末尾添加一个换行符 (PS):a
循环名称空间s/^\n//;t
当换行符位于 PS 的前面时,将其删除并打印行s/^(\S+|\s+)(.*)\n/\2\n\1/;ta
在换行符之后直接插入非空格或空格字符串并循环到:a
该-r
开关使正则表达式更易于使用(分组(...)
、交替...|...
和一个或多个的元字符+
不再需要反斜杠前缀)。
选择:
sed -E 'G;:a;s/^(\S+)(\s*)(.*\n)/\3\2\1/;ta;s/.//' file
注意要反转线,请将上述解决方案调整为:
sed -E 'G;:a;/^(.)(.*\n)/\2\1/;ta;s/.//' file
可能你会喜欢 perl:
perl -F -lane '@rev=reverse(@F);print "@rev"' your_file
正如伯恩哈德所说,tac
可以在这里使用:
#!/usr/bin/env bash
set -eu
echo '1 2 3
2 3 4
3 4 5' | while IFS= read -r; do
echo -n "$REPLY " | tac -s' '
echo
done
$ ./1.sh
3 2 1
4 3 2
5 4 3
我相信我的例子更有帮助。