使用命令行删除文本?

时间:2014-08-07 21:47:53

标签: perl shell text command-line

我有一个巨大的文件,其中包含遵循以下格式的行:

New-England-Center-For-Children-L0000392290
Southboro-Housing-Authority-L0000392464
Crew-Star-Inc-L0000391998
Saxony-Ii-Barber-Shop-L0000392491
Test-L0000392334

我想要做的就是将其缩小到这一点:

New-England-Center-For-Children
Southboro-Housing-Authority
Crew-Star-Inc
Test

任何人都可以帮忙吗?

6 个答案:

答案 0 :(得分:2)

使用GNU awk

awk -F\- 'NF--' OFS=\- file
New-England-Center-For-Children
Southboro-Housing-Authority
Crew-Star-Inc
Saxony-Ii-Barber-Shop
Test
  • 将输入和输出字段分隔符设置为-
  • NF包含多个字段。将其减少1以删除最后一个字段。

使用sed

sed 's/\(.*\)-.*/\1/' file
New-England-Center-For-Children
Southboro-Housing-Authority
Crew-Star-Inc
Saxony-Ii-Barber-Shop
Test
  • 简单的贪婪正则表达式匹配最后一个连字符。
  • 在替换时使用捕获的组并丢弃其余组。

答案 1 :(得分:1)

问题的第1版

输入的第一个版本是HTML格式,必须在所需文本之前和之后删除部分:

$ sed -r 's|.*[A-Z]/([a-zA-Z-]+)-L0.*|\1|' input
Special-Restaurant
Eliot-Cleaning
Kennedy-Plumbing

问题的第2版

在修订后的问题中,只需删除以-L00开头的文字:

$ sed 's|-L00.*||' input2
New-England-Center-For-Children
Southboro-Housing-Authority
Crew-Star-Inc
Saxony-Ii-Barber-Shop
Test

这两个命令都使用单个"替换"命令。该命令的格式为s|old|new|

答案 2 :(得分:1)

这个perl代码是:perl -nle'print $1 if(m{-.*?/(.*?-.*?)-})

我们可以将正则表达式分解为匹配以下内容:

  • -表示城市和州之间的情况
  • .*?匹配使正则表达式工作的最小字符集,即状态
  • /匹配State和您想要的数据之间的斜杠
  • (开始捕获您感兴趣的数据
  • .*?-.*?将与您关注的数据相匹配
  • )将关闭捕获
  • -将匹配L #######之前的破折号,以便在数据之后为正则表达式提供匹配的内容。这将阻止最小的正则表达式匹配0个字符。

然后print语句将打印出捕获的内容(您的数据)。

答案 3 :(得分:0)

awk喜欢这些东西:

$ awk -F[/-] -v OFS="-" '{print $(NF-3), $(NF-2)}' file
Special-Restaurant
Eliot-Cleaning
Kennedy-Plumbing

这会将/-设置为可能的字段分隔符。基于它们,它打印由分隔符-分隔的last_field-3和last_field-2。请注意,$NF代表最后一个参数,因此$(NF-1)是倒数第二个,等等。


sed也很有用:

$ sed -r 's#.*/(\w*-\w*)-\w*\.\w*</loc>$#\1#' file
Special-Restaurant
Eliot-Cleaning
Kennedy-Plumbing

在斜杠word-word之后选择块/,然后跟word.word</loc> + end_of_line。然后,它打印回这个块。


更新

根据您的新输入,可以实现:

$ sed -r 's/(.*)-L\w*$/\1/' file
New-England-Center-For-Children
Southboro-Housing-Authority
Crew-Star-Inc
Saxony-Ii-Barber-Shop
Test

选择块-L +某物+行尾的所有内容,并将其打印回来。

您还可以使用另一种技巧:

rev file | cut -d- -f2- | rev

正如你想要的那样,每一片-个分隔的字段,让我们得到所有这些,但最后一个。怎么样?通过反转线,将所有线从第二个线上移开然后反转。

答案 4 :(得分:0)

以下是我用Perl做的事情:

perl -nle 'm{example[.]com/bp/(.*?)/(.*?)-L\d+[.]htm} && print $2' filename

注意:原始问题是匹配输入行,如下所示:

<loc>http://www.example.com/bp/Lowell-MA/Special-Restaurant-L0000423916.htm</loc>
<loc>http://www.example.com/bp/Houston-TX/Eliot-Cleaning-L0000422797.htm</loc>
<loc>http://www.example.com/bp/New-Orleans-LA/Kennedy-Plumbing-L0000423121.htm</loc>

-n选项告诉Perl循环遍历文件的每一行(但不打印出来)。

-l选项在每个打印的末尾添加换行符

-e&#39; perl-code&#39;选项为每行输入执行perl-code

模式:

/regex/ && print

仅在正则表达式匹配时才会打印。如果正则表达式包含捕获括号,您可以将第一个捕获的部分称为$ 1,第二个作为$ 2等。

如果你的正则表达式包含斜杠,使用不同的正则表达式分隔符可能更清晰(&#39; m&#39;代表&#39;匹配&#39;):

m{regex} && print

如果你有一个现代的Perl,你可以使用-E来启用现代功能,并使用say而不是print来打印附加的换行符:

perl -nE 'm{example[.]com/bp/(.*?)/(.*?)-L\d+[.]htm} && say $2' filename

答案 5 :(得分:0)

这在Perl中非常简洁

perl -i.bak -lpe's/-[^-]+$//' myfile

请注意,这会修改输入文件就地,但会保留原始数据的备份,并调用myfile.bak