How to replace characters only on certain lines

sedtext processing

I need to replace single quotes with double quotes AND double quotes with single quotes in over 600 files. I've been reading various topics most of the day. I am hampered by only knowing some basic shell scripting commands and an unfamiliarity with regexp.

Below is a sample file I've made a bit generic.

   some text KEYWORD_1 table name column = "string" AND column = "string"
    Additional text
          .
          .
          .
   some text KEYWORD_2 text 'text in quote' etc. 

I only want to change the quotes on the 2 lines with KEYWORDs. I can't guarantee the keywords are always going to be first line and last line. I need my solution to find the keyword and change all the quotes on that line only.

I tried some things I found in sort of similar questions on this forum, including a meta on SED. I tried to figure out how to use this command: sed -i 's/foo\(.*baz\)/bar\1/' file. According to that topic the command, "Replaces foo with bar only if there is a baz later on the same line." My keyword is not later on the same line its at the beginning and I couldn't make it work for me.

I also tried ex -sc 'g/DEL/s/ALF/BRA/g' -cx file that didn't do anything. I'm assuming it can't be executed from the command line. I really don't want to open each of 600 files.

At one point I tried, grep KEYWORD_1 file | sed -i "s/'/\"/g" file
Of course, that changed all the quotes in the file not just the one line.

I'm betting the solution is simple and I just can't see it. How can I do this?

As requested my desired output is:

some text KEYWORD_1 table name column = 'string' AND column = 'string'
    Additional text
          . 
          .
          .
some text KEYWORD_2 text "text in quote" etc.

Best Answer

The complication here is that if you replace all ' with " and then all " with ', you will be left with only '. So, you will first need to replace ' with something else—for example, the NULL character (\0) which you can safely assume won't be in your input file—then " with ' and then replace that something else with " again. For example, in perl:

$ perl -pe "if(/KEYWORD){s/'/\0/g; s/\"/'/g; s/\0/\"/g}" file
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
      .
      .
      .
KEYWORD_2 text "text in quote" etc. 

Explanation

  • -pe : print each input line after applying the script given by -e.
  • if(/KEYWORD/){something} : do something only if this line matches KEYWORD.
  • s/foo/bar/g : replace all occurrences of foo in the line with bar. The g means "global". Without it, only the 1st occurrence on each line would be replaced.

Note that since the script itself is inside double quotes, the double quotes inside the script need to be escaped (\").


As pointed out in the comments, there's a more direct way I should have thought of in the first place:

perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file

The tr operator transliterates lists of characters. The general format is tr/searchlist/replacementlist/. So this will replace all ' with " and all " with ' only on lines matching KEYWORD.

Related Question