How to use sed to insert a line before each line in a file with the original contents of the line surrounded by the line?

I am trying to use sed (GNU sed version 4.2.1) to insert a line before each line in a file with the contents of the line surrounded by the line.

Input:

truncate table ALPHA; truncate table BETA; delete from TABLE_CHARLIE where ID=1; 

Expected Result:

 SELECT 'truncate table ALPHA;' from dual; truncate table ALPHA; SELECT 'truncate table BETA;' from dual; truncate table BETA; SELECT 'delete from TABLE_CHARLIE where ID=1;' from dual; delete from TABLE_CHARLIE where ID=1; 

I tried using the special ampersand character (&), but this does not seem to work. If I put something after the ampersand on the replacement string, the result will be wrong.

Attempt 1:

 sed -e "s/\(.*\)/SELECT '&\n&/g" input.txt output: SELECT 'truncate table ALPHA; truncate table ALPHA; SELECT 'truncate table BETA; truncate table BETA; SELECT 'delete from TABLE_CHARLIE where ID=1; delete from TABLE_CHARLIE where ID=1; 

With the previous code, I get SELECT ' as expected, but as soon as I try to add ' from dual; to the right of the line, everything will fail.

Attempt 2:

 sed -e "s/\(.*\)/SELECT '&' from dual;\n&/g" input.txt output: ' from dual;cate table ALPHA; truncate table ALPHA; ' from dual;cate table BETA; truncate table BETA; SELECT 'delete from TABLE_CHARLIE where ID=1;' from dual; 
+5
source share
4 answers

You can use the hold space to temporarily save the original row.

 sed "h;s/.*/'SELECT '&' from dual;/;p;g" input.txt 

or more readable:

 sed " h s/.*/'SELECT '&' from dual;/ p g" input.txt 

Here is the breakdown of the team.

  • First, each line of input is placed in the template space.
  • The h command copies the contents of the template space to the hold space.
  • The s command performs wildcard substitution. & represents everything that has been matched. This command leaves unused space.
  • The p command prints the contents of the template space to standard output.
  • The g command copies the contents of the hold space to the drawing space.
  • By default, the contents of the template space are written to standard output before reading the next line of input.

As Glenn Jackman points out, you can replace p;g with g . This creates a two-line value in the template space, which is then printed rather than printed in two separate template spaces.

 sed "h;s/.*/'SELECT '&' from dual;/;G" input.txt 

In addition, you can add comments to the sed command so that you can understand what linear noise is later :) if it is in a script.

 sed " # The input line is first copied to the pattern space h # Copy the pattern space to the hold space s/.*/'SELECT '&' from dual;/ # Modify the pattern space p # Print the (modified) pattern space g # Copy the hold space to the pattern space # The output of the pattern space (the original input line) is now printed " input.txt 
+5
source

Your second attempt works both with sed versions, and with 4.2.1 and 4.2.2. I got the same invalid input when I tried to save your input file with the end of the Windows line (line feed and carriage return).

Use this command in your source file before running the sed command:

 tr -d '\15\32' < winfile.txt > unixfile.txt 

Or, as you suggest, simply using the dos2unix utility.

+1
source

If you are looking for an alternative to sed, these work:

 awk '{printf "SELECT '\''%s'\'' from dual;\n%s\n", $0, $0}' file 
 perl -lpe "print qq{SELECT '\$_' from dual;}" file 
+1
source

Here's how to do it with awk :

 awk -v PRE="SELECT '" -v SU="' from dual;" '{print PRE$0SU; print}'` 
0
source

Source: https://habr.com/ru/post/1259508/


All Articles