Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I swap two lines using sed?

Tags:

linux

sed

Does anyone know how to replace line a with line b and line b with line a in a text file using the sed editor?

I can see how to replace a line in the pattern space with a line that is in the hold space (i.e., /^Paco/x or /^Paco/g), but what if I want to take the line starting with Paco and replace it with the line starting with Vinh, and also take the line starting with Vinh and replace it with the line starting with Paco?

Let's assume for starters that there is one line with Paco and one line with Vinh, and that the line Paco occurs before the line Vinh. Then we can move to the general case.

like image 374
David Avatar asked Oct 21 '10 21:10

David


3 Answers

#!/bin/sed -f
/^Paco/ {
:notdone
  N
  s/^\(Paco[^\n]*\)\(\n\([^\n]*\n\)*\)\(Vinh[^\n]*\)$/\4\2\1/
  t
  bnotdone
}

After matching /^Paco/ we read into the pattern buffer until s// succeeds (or EOF: the pattern buffer will be printed unchanged). Then we start over searching for /^Paco/.

like image 163
smilingthax Avatar answered Sep 28 '22 02:09

smilingthax


cat input | tr '\n' 'ç' | sed 's/\(ç__firstline__\)\(ç__secondline__\)/\2\1/g' | tr 'ç' '\n' > output

Replace __firstline__ and __secondline__ with your desired regexps. Be sure to substitute any instances of . in your regexp with [^ç]. If your text actually has ç in it, substitute with something else that your text doesn't have.

like image 28
vbuterin Avatar answered Sep 28 '22 04:09

vbuterin


try this awk script.

s1="$1"
s2="$2"
awk -vs1="$s1" -vs2="$s2" '
{ a[++d]=$0 }
$0~s1{ h=$0;ind=d}
$0~s2{
 a[ind]=$0
 for(i=1;i<d;i++ ){ print a[i]}
 print h
 delete a;d=0;
}
END{ for(i=1;i<=d;i++ ){ print a[i] } }' file

output

$ cat file
1
2
3
4
5

$ bash test.sh 2 3
1
3
2
4
5

$ bash test.sh 1 4
4
2
3
1
5

Use sed (or not at all) for only simple substitution. Anything more complicated, use a programming language

like image 40
ghostdog74 Avatar answered Sep 28 '22 04:09

ghostdog74