[英]Reverse input order with sed
I have a file, lets call it 'a.txt' and this file contains the following text line我有一个文件,我们称之为“a.txt”,该文件包含以下文本行
do to what
I'm wondering what the SED command is to reverse the order of this text to make it look like我想知道 SED 命令是什么来反转文本的顺序以使其看起来像
what to do
Do I have to do some sort of append?我必须做某种附加吗? Like append 'do' to 'to' so it would look like
就像将“do”附加到“to”一样,它看起来像
to ++ do (used ++ just to make it clear) to ++ do(使用 ++ 只是为了清楚起见)
I know tac
can do something related我知道
tac
可以做一些相关的事情
$ cat file
do to what
$ tac -s' ' file
what to do $
Where the -s
defines the separator, which is by default a newline.其中
-s
定义分隔符,默认情况下是换行符。
I would use awk
to do this:我会使用
awk
来做到这一点:
awk '{ for (i=NF; i>=1; i--) printf (i!=1) ? $i OFS : $i "\n" }' file.txt
Results:结果:
what to do
EDIT :编辑:
If you require a one-liner to modify your file "in-place", try:如果您需要单线来“就地”修改您的文件,请尝试:
{ rm file.txt && awk '{ for (i=NF; i>=1; i--) printf (i!=1) ? $i OFS : $i "\n" }' > file.txt; } < file.txt
As this question was tagged sed , my 1st answer was:由于这个问题被标记为sed ,我的第一个答案是:
First (using arbitraty _
to mark viewed spaces, when a.txt
contain do to what
:首先(使用仲裁
_
标记查看的空间,当a.txt
包含do to what
:
sed -e '
:a;
s/\([^_]*\) \([^ ]*\)/\2_\1/;
ta;
y/_/ /;
' a.txt
what to do
than, when a.txt
contain do to to what
:比,当
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
There is one +
for each supressed duplicated word:每个被压制的重复词都有一个
+
:
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+
But as there is a lot of people searching for simple bash solutions, there is a simple way:但是因为有很多人在寻找简单的bash解决方案,所以有一个简单的方法:
xargs < <(uniq <(tac <(tr \ \\n <<<'do do to what what what what')))
what to do
this could be written:这可以写成:
tr \ \\n <<<'do do to what what what what' | tac | uniq | xargs
what to do
or even with some bash scripting:甚至使用一些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
}
Will do:会做:
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
}
where submited string have to be submitted as argument:其中提交的字符串必须作为参数提交:
revcnt do do to what what what what
what+++ to do+
Or if prossessing standard input (or from file) is required:或者,如果需要处理标准输入(或来自文件):
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
}
So you can process multiple lines:所以你可以处理多行:
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+
This might work for you (GNU sed):这可能对你有用(GNU sed):
sed -r 'G;:a;s/^\n//;t;s/^(\S+|\s+)(.*)\n/\2\n\1/;ta' file
Explanation:解释:
G
add a newline to the end of the pattern space (PS) G
在模式空间的末尾添加一个换行符 (PS):a
loop name space :a
循环命名空间s/^\\n//;t
when the newline is at the front of the PS, remove it and print line s/^\\n//;t
当换行在 PS 前面时,去掉并打印 lines/^(\\S+|\\s+)(.*)\\n/\\2\\n\\1/;ta
insert either a non-space or a space string directly after the newline and loop to :a
s/^(\\S+|\\s+)(.*)\\n/\\2\\n\\1/;ta
在换行符后直接插入非空格或空格字符串并循环到:a
The -r
switch makes the regexp easier-on-the-eye (grouping (...)
, alternation ...|...
and the metacharacter for one-or-more +
are relieved of the need of a backslash prefix). -r
开关使正则表达式更容易理解(分组(...)
、交替...|...
和一个或多个+
的元字符不再需要反斜杠前缀) .
Alternative:选择:
sed -E 'G;:a;s/^(\S+)(\s*)(.*\n)/\3\2\1/;ta;s/.//' file
NB To reverse the line, adapt the above solution to:注意要反转线,请将上述解决方案调整为:
sed -E 'G;:a;/^(.)(.*\n)/\2\1/;ta;s/.//' file
可能你会为此想要 perl:
perl -F -lane '@rev=reverse(@F);print "@rev"' your_file
As Bernhard said , tac
can be used here:正如伯恩哈德所说,
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
I believe my example is more helpful.我相信我的例子更有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.