AlwynIsPat
AlwynIsPat

Reputation: 719

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:

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.

Upvotes: 4

Views: 10223

Answers (6)

potong
potong

Reputation: 58351

This might work for you:

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

Upvotes: 0

johnsyweb
johnsyweb

Reputation: 141770

This is a job for sed! From the GNU sed homepage:

Sed is typically used for extracting part of a file using pattern matching or substituting multiple occurrences of a string within a file.

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:'
  • s!search!replace! replaces 'search' with 'replace' where 'search' is a regular expression
  • \1 is the string captured by the first matching group "\(...\)"
  • \2 is the string captured by the second matching group "\(...\)"

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.

Upvotes: 4

SiegeX
SiegeX

Reputation: 140227

Here are improved answers with awk and sed.

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. All they require is that '.deb' file is at the end of the path

Sed

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

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 '/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 -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

Upvotes: 0

ChrisWue
ChrisWue

Reputation: 19020

You are looking for a tool called sed:

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

Upvotes: 0

viraptor
viraptor

Reputation: 34145

Not in bash itself, but:

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

Upvotes: 0

fge
fge

Reputation: 121702

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. Then re-add the i.

Upvotes: 1

Related Questions