0

I want to remove ";" from line if it is not followed by "number" + "=" sign. e.g.

echo "32=rtys;54tyu;45_fd;62=xyz;fdg"
output should be "32=rtys54tyu45_fd;62=xyzfdg"

I tried below but it worked only for letters.

sed 's/;\($\|[^[:digit:]=]\)/\1/g' 

but it only works for ;+letters and not others.

  • 1
    In the title you say "based on next 2 characters" but in your example the thing you're calling a "number" seems to be a 2-digit number, so the algorithm seems to depend on more than the next two characters. – znt Sep 26 '16 at 21:56
  • 1
    Your example does not match with your conditions. – heemayl Sep 26 '16 at 21:57
  • use a pattern match in the address expression to match the lines you want to do a replacement on. – Barmar Sep 26 '16 at 22:12

3 Answers3

2

Using sed

$ s="32=rtys;54tyu;45_fd;62=xyz;fdg"
$ sed -E 's/;/\n/g; s/\n[0-9]+=/;&/g; s/\n//g' <<<"$s"
32=rtys54tyu45_fd;62=xyzfdg

This works in three steps:

  1. s/;/\n/g replaces all semicolons with newlines. Because, by default, sed takes input one line at a time, the pattern space will never have a newline to start. Thus will be no confusion.

  2. s/\n[0-9]+=/;&/g puts a semicolon in front of any newline followed by a number followed by an equal sign.

  3. s/\n//g removes all newlines.

The above was tested on GNU sed. For BSD/OSX, some changes will likely be needed. The following might work:

sed -E $'s/;/\n/g; s/\n[0-9]+=/;&/g; s/\n//g' <<<"$s"

Using awk

$ s="32=rtys;54tyu;45_fd;62=xyz;fdg"
$ awk -F\; '{$1=$1; for (i=2;i<=NF;i++) if ($i~/^[0-9]+=/) $i=";"$i} 1' OFS="" <<<"$s"
32=rtys54tyu45_fd;62=xyzfdg

This works by using ; as the field separator on input and the empty string as a field separator on output. This would remove all ; except that we check each field: if a field begins with number+=, we add a semicolon to the beginning of that field.

John1024
  • 109,961
  • 14
  • 137
  • 171
0
$ sed -E 's/a/aA/g; s/;([0-9]+=)/aB\1/g; s/;//g; s/aB/;/g; s/aA/a/g' file
32=rtys54tyu45_fd;62=xyzfdg

This is a common, idiomatic approach - see https://stackoverflow.com/a/38153467/1745001 for an explanation.

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

Easy to do with negative lookahead:

$ echo "32=rtys;54tyu;45_fd;62=xyz;fdg" | perl -pe 's/;(?!\d+=)//g'
32=rtys54tyu45_fd;62=xyzfdg
  • ;(?!\d+=) means ; not followed by one or more digits and =
Graham
  • 7,431
  • 18
  • 59
  • 84
Sundeep
  • 23,246
  • 2
  • 28
  • 103