3

我们如何从 unix 文件的倒数第二行删除字符?

例如,我有一个内容如下的文件:

aaa
bbb*
ccc*
ddd*
eee

我的输出应该是:

aaa
bbb*
ccc*
ddd
eee

对此有什么想法吗?

4

5 回答 5

5

使用 sed 一次性完成此操作的通用方法是使用滑动窗口,类似于GNU sed 手册中描述的内容。

由于您只对倒数第二行的替换感兴趣,因此不需要保留空间。在这种情况下,一个N就足够了:

sed 'N; $! { P; D; }; s/.\n/\n/'

或作为 BSD sed 兼容脚本:

sed 'N; $! { P; D; }; s/.\n/\
/'

输出:

aaa
bbb*
ccc*
ddd
eee

解释

  • N命令将第二行添加到模式空间。
  • $!当我们还没有到达最后一行时,该块被评估。
  • { P; D; }打印第一行模式空间并将其删除。如果模式空间不为空,则具有重新启动脚本的D副作用。
  • 仅当最后两行在模式空间中时才评估替换命令。
于 2013-04-03T11:53:28.410 回答
2

脑海中浮现出三种通用方法。

用于wc -l file获取行数:

awk 'NR==n-1{sub(/.$/,"")}1' n=$(wc -l file)
aaa
bbb*
ccc*
ddd
eee

解析文件两次:

awk 'FNR==NR{n++;next}FNR==n-1{sub(/.$/,"")}1' file file
aaa
bbb*
ccc*
ddd
eee

处理前后反转文件:

tac file | sed '2s/.$//' | tac
aaa
bbb*
ccc*
ddd
eee
于 2013-04-03T11:18:20.303 回答
2

重用的好时机ed,一次:

简短版:

{ echo '$-1s/.$//' ; echo "w" ; } | ed file_to_modify.txt >/dev/null

带有一些“调试信息”的版本^^:

{ echo 'doing: $-1s/.$//' >&2 ; echo '$-1s/.$//' ; echo "doing: w" >&2 ; echo "w" ; echo "C" >&2 ; } | ed file_to_modify.txt

简而言之:ed非常接近 vi,但一次只能在 1 行上工作...我只是在第 n-1 行告诉它 's/.$//' (将一行的最后一个字符替换为任何内容) ($= ed 中的最后一行,$-1 = 最后一行 - 1)

于 2013-04-03T11:25:20.360 回答
1

使用vivim或任何编辑器打开文件并根据需要编辑文件

于 2013-04-03T10:51:12.183 回答
0

用 awk 直截了当:

awk '{a[NR]=$0}END{for(i=1;i<=NR;i++){if(i==NR-1)sub(/.$/,"",a[i]);print a[i]}}' file

awk 有点棘手:

awk '{if(f>1)print p;p=l;f++;l=$0}END{sub(/.$/,"",p);print p;print l}' file
于 2013-04-03T10:55:55.113 回答