从命令行删除每行的第一个和最后一个字符


8

我正在尝试在文本文件中删除每行的第一个和最后一个字符,并将截断的版本保存在新文件中。是否有人对使用awk大型文件专用的Linux程序或命令有效地做到这一点?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

预期的output.txt

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2

Answers:


14

仅此而已的另一种方式:

rev input | cut -c2- | rev | cut -c2-

(注意:使用GNU时cut,它仅适用于仅由一个字节组成的字符(如您的示例))。


真好!这比到目前为止提出的sed和awk解决方案快得多。
吉尔(Gilles)'所以

我为害怕sed / awk / regex语法的人们提出了这个答案,但是我想不到它的速度更快,特别是对于具有三个管道并通过每个管道传递全部内容的大型文件。可能会认为sed或awk一次读取一行对于大型文件会更有效。
德雷克·克拉里斯

3
猜猜这就是其中许多* nix实用程序40多年的优化将为您带来的好处!
德雷克·克拉里斯2013年

@Gilles,对于某些形式的输入,在utf8语言环境中GNU sed的速度更快,它取决于您是否考虑挂钟时间或CPU时间。ssed或Heirloom工具箱sed可以达到更好的性能。
斯特凡Chazelas

@Gilles在Solaris 5.10中没有用于修订的MAN条目。我最终使用了sed
ayrton_senna 2015年

10

根据您的问题,请从输入文件中删除最后一个和第一个单词,如下所示:

sed 's/.$//; s/^.//' inputfile

如果您可以将它们与其他解决方案进行基准比较,那就太好了s/.\(.*\).$/\1/。由于不使用反向引用,因此速度可能会更快,并且该问题确实提到了“大文件”。
l0b0

4
我用测试的@ l0b0 time yes | head -n 10000000 | COMMAND >/dev/null。我得到rev input | cut -c2- | rev | cut -c2-→0.14s,sed 's,.\(.*\).$,\1,'→3.38s; awk '{print substr($0,2,length()-2);}'→3.50秒;sed 's/.$//; s/^.//'→5.09秒。
吉尔斯(Gilles)'所以

@吉尔斯+1应该是一个答案。
13年

2
@吉尔斯,那是很短的一行。我发现对于30个字符的宽行,使用RNU sed的@RahulPatil解决方案是@juampa的3倍。也。sed 's/.\(.*\)./\1/'似乎比sed 's/^.\(.*\).$/\1/'(GNU再次sed)快。而且,性能取决于语言环境(对字符的解释)和sed实现(就此而言,从传家宝工具箱中获得的s比GNU sed的速度要快得多)。
斯特凡Chazelas

5

一如既往,有很多可能性

sed 's,.\(.*\).$,\1,g' your_file

说明

  • , -sed分隔符也可以是任何其他字符,因为只要需要它就可以转义。
  • . 匹配一个字符
  • \(.*\) -对其余部分进行分组,并将其存储以备进一步检索。
  • . 再次匹配一个字符
  • $ - 行结束
  • \1 -输出与上面的组匹配的文本
  • g 在线更换全局。

2
为什么g呢 每行只有一场比赛。
njsg 2013年

请注意,它不会从少于2个字符的行中删除任何内容。
斯特凡Chazelas

3

awk如果愿意,也可以使用

awk '{print substr($0,2,length()-2);}' input.txt > output.txt

2
tr -d '()[]{}"' < your_file

这也应该起作用。很好地将每个字符“翻译”为无(删除)。

缺点是,如果它们不是第一个/最后一个字符,也会删除它们。它还会错过您未在中列出的任何结尾字符()[...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.