combine sed commands that switch line order in a file with bash

Related searches

I have repeating sed commands that switch line 1 and 2, 3 and 4 etc... I would like to combine these commands into one sed command. However when i attempt to combined them it adds duplicate lines and will eliminate some lines.

Edit:

The orininal file out out before sed looks like:

Some code....
Some code...
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
some more...
some more...

The code that gives the desired output is:

sed -i '2{h;d};3{p;x}' file.txt && sed -i '4{h;d};5{p;x}' file.txt && sed -i '6{h;d};7{p;x}' file.txt 

The code i would like to use is:

sed -i '2{h;d};3{p;x};4{h;d};5{p;x};6{h;d};7{p;x}' file.txt

With a desired output from an ordered file of

Some code...
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
some more...
some more...

This might work for you (GNU sed):

sed '3,8{N;s/\(.*\)\n\(.*\)/\2\n\1/}' file

For a range of lines, append the following line and using pattern matching, swap them.

If you wanted swap say lines 3-4 and 7-8 use:

sed '3ba;7ba;b;:a;N;s/\(.*\)\n\(.*\)/\2\n\1/' file

Or swap lines 3-5 and 6-8, use:

sed '3,8{N;N;s/\(.*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/} file

Multiple commands syntax (sed, a stream editor), Using newlines is most natural when running a sed script from a file (using the -f option). On the command line, all sed commands may be separated by newlines. following a , c , i commands are taken as the text to append/change/insert. Using a following the e command until the end of the line will be sent to the shell. Using the join command (only for files with less fields) $ join -t, -o 1.2,1.1,1.3 file file 25,Linux,1 30,Solaris,2 15,HPUX,3 28,AIX,4 Using the join command , the input file is joined with itself which is done just to fulfill the syntax of join where it needs 2 files to join.

This is a completely inappropriate task for sed. Just use awk, e.g. with GNU awk for "inplace" editing since that seems to be a priority for some reason and using a modified sample input file so it's clear which lines are and are not being swapped:

$ cat file
with a some code here
and a some code there
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
here a code, there a code
everywhere a code, code

$ awk -i inplace 'NR>=3 && NR<=8{if ((++c)%2) p=$0; else print $0 ORS p; next} 1' file

$ cat file
with a some code here
and a some code there
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
here a code, there a code
everywhere a code, code

Other than the GNU-only -i inplace syntactic sugar instead of > tmp && mv tmp file, the script will work using any awk in any shell on any UNIX box.


Original response and other examples below:

$ awk 'NR%2{p=$0;next} {print $0 ORS p}' file
Some code...
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e

The above will work using any awk in any shell on any UNIX box.

Only want to swap between lines 4 and 7, say? That's a trivial tweak because it's the right tool for the job:

$ seq 10 | awk 'NR<=3 || NR>=8{print; next} (++c)%2{p=$0;next} {print $0 ORS p}'
1
2
3
5
4
7
6
8
9
10

or if you prefer:

$ seq 10 | awk 'NR>=4 && NR<=7{if ((++c)%2) p=$0; else print $0 ORS p; next} 1'
1
2
3
5
4
7
6
8
9
10

Want to reverse every 3 lines? Again, trivial because it's the right tool for the job:

$ seq 9 | awk 'NR%3{p2=p1;p1=$0;next} {print $0 ORS p1 ORS p2}'
3
2
1
6
5
4
9
8
7

Hopefully you get the picture...

50 `sed` Command Examples – Linux Hint, Any particular string in a text or a file can be searched, replaced and deleted by a file; Match a multi-line pattern and replace with new multi-line text; Replace order of Combine sed with other commands; Insert an empty line in a file; Delete all The following `sed` command will replace the 'Count' value in the line that� Each sed command consists of an optional address or address range (for instance, line numbers specifying what part of the file to operate on; see Selecting Lines for details), followed by a one-character command name and any additional command-specific code.

Assuming you're using GNU sed, ($!) unless current line is the last line in the file, (x) swap contents of pattern space and hold space, (n) read a new line into pattern space, (G) append the content of hold space to pattern space with a line feed. (p) Print the contents of pattern space.

$ cat file
one
two
three
four
five
six
seven
$
$ sed -n -i '$!{x;n;G};p' file
$
$ cat file
two
one
four
three
six
five
seven

To make it a hundred percent POSIX compatible you need to give up on inplace editing and break the script into multiple commands:

sed -n -e '$!{x;n;G;}' -e 'p' file

This answers the first version of OP's question. Since with their latest edits it became undecipherable, I refuse to edit.

Unix Sed Tutorial: How To Execute Multiple Sed Commands, Question: Is it possible for me to combine multiple sed commands? Can I combine two sed Linux - Sysadmin, Scripting etc. 2. Databases This sed example deletes 4th and 2nd line from the file thegeekstuff.txt. Using “-e” To change “a” by “x” in every 50th line of a file, use the following. $ sed ' :loop The shell then runs the above command sed with the next arguments (assuming pattern=bert and file=text.txt):-i s,bert,Say hurrah to &: \0/, text.txt If file.txt contains bert, the output will be: Say hurrah to bert: \0/

There is an arguably simpler GNU sed solution1 to this problem:

1,2b   # In the range 1,2 ...
9,$b   # ... and also in 9,$, auto print and end this cycle.
3~2 {  # From line 3 and every second line thereafter,
  h    # hold, then
  d    # delete, and end this cycle.
}
G      # On every other line, append hold space and auto print.

Testing:

# test.sh

cat > FILE <<EOF
Some code....
Some code...
Line-a
Line-b
Line-c
Line-d
Line-e
Line-f
Some more code...
Some more code...
EOF

sed '1,2b; 9,$b; 3~2{h;d}; G' FILE

Output:

Some code....
Some code...
Line-b
Line-a
Line-d
Line-c
Line-f
Line-e
Some more code...
Some more code...

Note that selecting lines by first~step e.g. 3~2 is a GNU extension.

This is based on a generic example of swapping lines in Chap. 6 of O'Reilly sed & awk 2nd ed.


1 But I agree with Ed Morton's comments that AWK is a better fit for this problem.

Join multiple sed commands in one script for processing CSV file , First of all, as Michael showed, you can just combine all of these into a single command: sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1. awk 'FS="---" {printf "%-22s ", $1}' < file1.txt > file1-pad.txt. Note: For FS, use a string that does not exist in file1.txt. 3) Use paste as you did before. $ paste file1-pad.txt file2.txt Languages Minimal automaton Recursively enumerable Turing machine Regular Finite.

The use of multiple sed statements on the command line, Unix & Linux Stack Exchange order by. active, oldest, votes. Up vote 3 Down vote. It's not only about combining multiple sed commands (Jasen expained that part in his You can drop the -c and replace the whole uniq with option -u to sort : Here it's starting to be weird without knowing the input file. However, the whole file needs to be loaded into memory): sort -uo file1 file1 sort -uo file2 file2 sort -um file1 file2 > mylist.merge mv mylist.merge originallist That would be faster than the simpler "one command line" to sort all: cat file1 file2 | sort -u >mylist.merge However, this line could be useful for small files.

To make the inner file print after the Pointer line, just switch the order of the patterns (you need to add a semicolon to get the default action), and you can drop the line variable: awk '//; /Pointer/ {while (getline<"innerfile") {print}}' outerfile >tmp mv tmp outerfile And just because no one has used perl yet,

Let us review some examples of write command in sed. 1. Write 1st line of the file. In this example, 1 (address) refers the first line of the input and w writes the pattern buffer to the output file “output.txt” $ sed -n '1w output.txt' thegeekstuff.txt $ cat output.txt 1. Linux - Sysadmin, Scripting etc. 2. Write first & last line of the file

Comments
  • Your example would be much clearer if the lines you don't want swapped weren't identical to each other!
  • This is exactly what i was looking for. Would you mind explaining the syntax.
  • yes im using GNU sed. I have edited the question to reflect more detail. Your answer shows me i need to use the correct switches. However i dont want to rearrange the whole file only particular lines.
  • Yes, the question did change a lot. I never saw that first version.
  • i wish i didnt have to but i edited the post again. Thats a clever solution with the tilde but i cant use it for "every line there after". Its completely my fault for not being thorough. I need to be able to select lines between upper and lower blocks of code and re arrange them. The Awk method is ok but re writing the file become weird. sed does on the spot replacement.
  • @goosegoose, I have updated based on your edit. If you know you have exactly 10 lines in your file, then you can actually use "every line thereafter".
  • I’m still testing and trying to understand why awk is better. Ultimately I wanted send to avoid sending it to a tmp file then overwrite. But it looks like awk can overwrite.
  • @goosegoose The truth is, without us understanding your actual use case, none of us can know which tool to use is the right one.
  • @goosegoose wrt you trying to understand why awk is better - imagine some small change in your requirements. Anything at all. Maybe print "swapping line number x for line number y" to stderr every time you swap them or ignore lines containing "X", whatever. Now update the sed script to do that and update the awk script to do that. THAT will teach you why awk is better for anything other than s/old/new/ - because an awk script is a structured C-like program that's easy to adapt while sed is a unique collection of arcane runes that's limited in functionality and differs for every application