ban*_*nuj 7 sed awk text-processing
我有一个带行的文件,就像这样:
A
B
C
Run Code Online (Sandbox Code Playgroud)
我想在 bash 中创建一个重复文件,其中包含与下一行的副本合并的每一行,例如:
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
Tor*_*rin 18
使用awk:
awk 'prev{ print prev ";" $0 }
{ prev = $0 }
END { if (NR) print prev ";" }'
Run Code Online (Sandbox Code Playgroud)
根据您的输入,给出
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
ste*_*ver 16
Quick'n'dirty 方式(涉及读取文件两次):
$ tail -n+2 file | paste -d';' file -
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
$ sed 'x;G;s_\n_;_;1d;${p;x;s_$_;_;}' file
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
该sed表达式正在做什么:
x: 将入行保存在保持空间中,并检索上一条G: 将新行(从保留空间)附加到旧行s_\n_;_: 用一个替换换行符;。1d: 如果这是第一行,将其删除(不要打印)并前进到下一行${...;}: 如果这是最后一行...p: 首先打印连接对x: 检索最后一行s_$_;_: 追加最终 ;sed没有保留空间的更简单的解决方案:
sed '$!N;y/\n/;/;p;y/;/\n/;D' file
Run Code Online (Sandbox Code Playgroud)
$!N加入下一行(如果有的话;当不在 POSIX 模式下时$!,GNUsed不需要)y/\n/;/ 将换行符替换为 ;p打印结果行y/;/\n/ 改回换行符,所以用D 你可以去掉第一行并继续下一行$ perl -lne 'print "$last;$_" if defined $last; $last=$_;END{print "$last;" if $.}' file
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
或者,如果你喜欢整个简洁的事情:
$ perl -lne'$.>1?print"$l;$_":1;$l=$_}{print"$l;"if$.' file
A;B
B;C
C;
Run Code Online (Sandbox Code Playgroud)
Vim 解决方案
可以发出此命令(感谢 Conspicuous Compiler 提出这一建议):
vim "+%s/\n\(.\+\)*/;\1\n\1" sample.txt
Run Code Online (Sandbox Code Playgroud)
或者,可能更习惯的是,启动 Vim 并打开文件并发出 ex 命令:
:%s/\n\(.\+\)*/;\1\n\1
Run Code Online (Sandbox Code Playgroud)
解释:
替换模式:
\n\(.+\)组成整个下一行的字符组。后面的量词*, 仅表示可以有零个或多个匹配项具有以下内容:
\1\n\1。后: