简体   繁体   English

如何使用bash替换多行?

[英]how to replace multiple lines using bash?

I have a file with thousands of lines. 我有一个包含数千行的文件。 I'm looking for help to modify multiple lines which i were to choose. 我正在寻找帮助来修改我选择的多行。

Package: com.xyz.abc
Version: 1.0
Filename: ./debs/abc.deb

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./debs/def.deb

I need a bash command to detect "Filename" then change them to something like this: 我需要一个bash命令来检测“Filename”,然后将它们更改为:

Package: com.xyz.abc
Version: 1.0
Filename: ./debs/download.php?p=abc

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./debs/download.php?p=def

And it will loop till all "Filename" have been changed. 它将循环直到所有“文件名”都被更改。

This is a job for sed ! 这是sed的工作! From the GNU sed homepage: 来自GNU sed主页:

Sed is typically used for extracting part of a file using pattern matching or substituting multiple occurrences of a string within a file. Sed通常用于使用模式匹配来提取文件的一部分或者在文件中替换多次出现的字符串。

Here is how you could do it: 您可以这样做:

sed '/^Filename:/s!\(./debs/\)\(.*\).deb!\1download.php?p=\2!' /path/to/input > /path/to/output

Where: 哪里:

  • /^Filename:/ looks for lines starting with ( ^ ) the text 'Filename:' /^Filename:/查找以( ^ )文本'Filename:'开头的行
  • s!search!replace! replaces 'search' with 'replace' where 'search' is a regular expression 将'search'替换为'replace',其中'search'是正则表达式
  • \\1 is the string captured by the first matching group " \\(...\\) " \\1是第一个匹配组“ \\(...\\) ”捕获的字符串
  • \\2 is the string captured by the second matching group " \\(...\\) " \\2是第二个匹配组“ \\(...\\) ”捕获的字符串

Demonstration: 示范:

$ echo 'Package: com.xyz.abc
Version: 1.0
Filename: ./debs/abc.deb

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./debs/def.deb' | sed '/^Filename:/s!\(./debs/\)\(.*\).deb!\1download.php?p=\2!' 
Package: com.xyz.abc
Version: 1.0
Filename: ./debs/download.php?p=abc

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./debs/download.php?p=def

For tweaking this and for writing your own sed scripts, please consult the online documentation . 有关调整此内容以及编写自己的sed脚本,请参阅在线文档

This is one solution: 这是一个解决方案:

perl -pi -e '/^Filename:/ and s,debs/([^.]+)\.deb\s*$,debs/download.php?p=$1,' thefile

First try it by not putting it the i option and pipe with less . 首先尝试它,不要把它与i选项和管道用less Then re-add the i . 然后重新添加i

不是在bash本身,而是:

sed 's#Filename: \./debs/\(.*\)\.deb#Filename: ./debs/download.php?p=\1#' < the_file

您正在寻找一个名为sed的工具:

sed -e "s|^(Filename: ./debs/)(.+).deb|\1download.php?p=\2|" < yourfile

Here are improved answers with awk and sed . 以下是awksed改进答案。

Unlike the other answers, these work independent of what the 'Filename:' path is. 与其他答案不同,这些工作与“文件名:”路径无关。 That is to say, if you change './debs/' to './myDebs/' it will still work. 也就是说,如果你将'./debs/'更改为'./myDebs/',它仍然有效。 All they require is that '.deb' file is at the end of the path 他们所需要的只是'.deb'文件位于路径的末尾

Sed 桑达

sed '/Filename:/s|^\(.*/\)\([^\.]*\)\..*$|\1download.php?p=\2|' ./infile

awk AWK

awk -F'/' '/Filename:/{split($NF,a,".");$NF="download.php?p=" a[1]}1' OFS='/' ./infile

Input 输入

$ cat ./infile
Package: com.xyz.abc
Version: 1.0
Filename: ./debs/abc.deb

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./MyDebs/def.deb

sed Output sed输出

$ sed '/Filename:/s|^\(.*/\)\([^\.]*\)\..*$|\1download.php?p=\2|' ./infile
Package: com.xyz.abc
Version: 1.0
Filename: ./debs/download.php?p=abc

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./MyDebs/download.php?p=def

awk Output awk输出

$ awk -F'/' '/Filename:/{split($NF,a,".");$NF="download.php?p=" a[1]}1' OFS='/' ./infile
Package: com.xyz.abc
Version: 1.0
Filename: ./debs/download.php?p=abc

Package: com.xyz.def
Version: 1.0.0-1
Filename: ./MyDebs/download.php?p=def

这可能对你有用:

 sed '/^Filename:/s/\([^/]*\)\.[^.]*$/download.php?p=\1/' file

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM