147

I'm on Linux command line and I have file with

127.0.0.1
128.0.0.0
121.121.33.111

I want

127.0.0.1:80
128.0.0.0:80
121.121.33.111:80

I remember my colleagues were using sed for that, but after reading sed manual still not clear how to do it on command line?

simhumileco
  • 31,877
  • 16
  • 137
  • 115
user2275580
  • 1,479
  • 2
  • 10
  • 3

7 Answers7

192

You could try using something like:

sed -n 's/$/:80/' ips.txt > new-ips.txt

Provided that your file format is just as you have described in your question.

The s/// substitution command matches (finds) the end of each line in your file (using the $ character) and then appends (replaces) the :80 to the end of each line. The ips.txt file is your input file... and new-ips.txt is your newly-created file (the final result of your changes.)


Also, if you have a list of IP numbers that happen to have port numbers attached already, (as noted by Vlad and as given by aragaer,) you could try using something like:

sed '/:[0-9]*$/ ! s/$/:80/' ips.txt > new-ips.txt

So, for example, if your input file looked something like this (note the :80):

127.0.0.1
128.0.0.0:80
121.121.33.111

The final result would look something like this:

127.0.0.1:80
128.0.0.0:80
121.121.33.111:80
summea
  • 7,390
  • 4
  • 32
  • 48
  • @Vlad Yes; but according to the OPs given example input... there shouldn't be any port numbers in the list of IPs. :) Even if there were... the OP could just run another sed `s///` beforehand to take out any port numbers at the end of each line. – summea Apr 12 '13 at 18:50
  • 1
    Ok, just clarifying... Maybe there should be a condition to exclude lines where a port already exists. – Vlad Apr 12 '13 at 18:52
  • 3
    `sed '/:[0-9]*$/ ! s/$/:80/'` – aragaer Apr 12 '13 at 18:57
  • @aragaer Did you want to post that as another answer? Or do you mind if I include that (with attribution) in this answer? It may be something the OP needs in the future, at least... – summea Apr 12 '13 at 20:14
  • 3
    Add it to your own answer. The suggestion to exclude lines with ports is already here in comments, I just wrote the exact command. – aragaer Apr 12 '13 at 20:45
  • 4
    If the file has CRLF terminators, the ``:80`` will be added to the beginning of the following line. Use ``dos2unix`` on the file first if necessary. – djnz0feh Feb 20 '18 at 11:23
  • 2
    is the `-n` necessary? probably not for most users. – jimh Jun 22 '20 at 20:34
71

Concise version of the sed command:

sed -i s/$/:80/ file.txt

Explanation:

  • sed stream editor
  • -i in-place (edit file in place)
  • s substitution command
  • /replacement_from_reg_exp/replacement_to_text/ statement
  • $ matches the end of line (replacement_from_reg_exp)
  • :80 text you want to add at the end of every line (replacement_to_text)
  • file.txt the file name

How can this be achieved without modifying the original file?

If you want to leave the original file unchanged and have the results in another file, then give up -i option and add the redirection (>) to another file:

sed s/$/:80/ file.txt > another_file.txt
simhumileco
  • 31,877
  • 16
  • 137
  • 115
  • Shell newbie here. How do we provide a variable name instead of :80 in this statment. The below statements didnt work for me. Thanks in advance. sed -i s/$/$value/ file.txt sed -i s/$/${value}/file.txt – Niketh Kovin Nov 23 '22 at 19:16
  • Hi @NikethKovin, both `sed -i s/$/$value/ file.txt` and `sed -i s/$/${value}/ file.txt` options work very well in my case. – simhumileco Nov 23 '22 at 19:47
21
sed 's/.*/&:80/'  abcd.txt >abcde.txt
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
sudhir
  • 227
  • 2
  • 2
  • Thank you very much for this easy to understand solution. I am using a modified version of this. if line does not end with `/`, add `/`. `sed 's#[^/]$#&/#' fix-url.txt > fix.txt`. – Ahmad Ismail Jan 17 '21 at 09:53
17

If you'd like to add text at the end of each line in-place (in the same file), you can use -i parameter, for example:

sed -i'.bak' 's/$/:80/' foo.txt

However -i option is non-standard Unix extension and may not be available on all operating systems.

So you can consider using ex (which is equivalent to vi -e/vim -e):

ex +"%s/$/:80/g" -cwq foo.txt

which will add :80 to each line, but sometimes it can append it to blank lines.

So better method is to check if the line actually contain any number, and then append it, for example:

ex  +"g/[0-9]/s/$/:80/g" -cwq foo.txt

If the file has more complex format, consider using proper regex, instead of [0-9].

kenorb
  • 155,785
  • 88
  • 678
  • 743
4
  1. You can also achieve this using the backreference technique

    sed -i.bak 's/\(.*\)/\1:80/' foo.txt
    
  2. You can also use with awk like this

    awk '{print $0":80"}' foo.txt > tmp && mv tmp foo.txt
    
k_vishwanath
  • 1,326
  • 2
  • 20
  • 28
2

Using a text editor, check for ^M (control-M, or carriage return) at the end of each line. You will need to remove them first, then append the additional text at the end of the line.

sed -i 's|^M||g' ips.txt
sed -i 's|$|:80|g' ips.txt
John
  • 29
  • 1
2

sed -i 's/$/,/g' foo.txt

I do this quite often to add a comma to the end of an output so I can just easily copy and paste it into a Python(or your fav lang) array

rich
  • 97
  • 1
  • 6
  • Worked for me to edit a bunch of CSV's to which I added a column and therefore needed an extra separator at the end of each line. Has the added benefit of adding it to the last line, while replacing linebreaks (\r) doesn't achieve that - grep -RiIl '\r' | xargs sed -i 's/\r/;\r/g' – user1298923 May 18 '22 at 10:05