0

I want to replace all the strings with DISPLAY="TRUE" to DISPLAY="FALSE" in the first line and vice versa in the next line in a single match.

Example: FROM:

 <SYN DISPLAY="TRUE" SEARCH="TRUE" CLASSIFY="TRUE">Appels</SYN>
 <SYN DISPLAY="FALSE" SEARCH="FALSE" CLASSIFY="TRUE">103.103117.1031171012</SYN>

TO

 <SYN DISPLAY="FALSE" SEARCH="TRUE" CLASSIFY="TRUE">Appels</SYN>
 <SYN DISPLAY="TRUE" SEARCH="FALSE" CLASSIFY="TRUE">103.103117.1031171012</SYN>

Note that all other strings in the corresponding line of <SYN DISPLAY="TRUE" or <SYN DISPLAY="FALSE" could be different.

The requirement is to match and replace only in the occurrence of both lines (shown above) i.e when <SYN DISPLAY="TRUE" is in 1st line and <SYN DISPLAY="FALSE" is in the second line. Single lines with the following example pattern should not be replaced.

<DIMENSION_NODE>
            <DVAL TYPE="EXACT">
               <DVAL_ID ID="4294960976"/>
               <SYN DISPLAY="TRUE" SEARCH="TRUE" CLASSIFY="TRUE">2</SYN>
            </DVAL>
         </DIMENSION_NODE>
    ```


I tried using sed, however, I couldn't make it work.

sed -E 's/(<SYN DISPLAY=\")TRUE(\".+\s+<SYN DISPLAY=\")FALSE(\".+<\/SYN>)/\1FALSE\2TRUE\3/' test.xml

Requesting experts help to make it work :)

Jerald Sabu M
  • 1,200
  • 3
  • 16
  • 19
  • Why manually editing those lines will not be enough for you, Jerald? All you need to do is to modify two lines of a single file? What `Note that all other strings in the corresponding line of ( ` means? – Quasímodo Apr 17 '20 at 21:24
  • @Quasímodo There is 2000+ such '2 line' patterns in the file., so its difficult to manually edit . Sorry that the "note" part incomplete (because it was not quoted), I have corrected it now. – Jerald Sabu M Apr 18 '20 at 05:37
  • Is it possible that the first line has `DISPLAY="FALSE"` and the second `DISPLAY="TRUE"`, and do they have to be changed? – Walter A Apr 18 '20 at 10:36
  • @WalterA No that is not in the file when I checked. So only DISPLAY="TRUE" in the first line needs to be changed to DISPLAY="FALSE" and DISPLAY="FALSE" in the 2nd line needs to be changed to DISPLAY="TRUE", but there can be just single line with "DISPLAY=true", this is an XML file by the way. – Jerald Sabu M Apr 18 '20 at 10:56

2 Answers2

1

From my point of view, the simplest way to achieve that, if you don't want to get into complicated regex, is to use a temporary value, like so:

sed \
    -e 's/DISPLAY="TRUE"/TMP/g' \
    -e 's/DISPLAY="FALSE"/DISPLAY="TRUE"/g' \
    -e 's/TMP/DISPLAY="FALSE"/g' YOUR_FILE

or, as a one-liner:

sed -e 's/DISPLAY="TRUE"/TMP/g' -e 's/DISPLAY="FALSE"/DISPLAY="TRUE"/g' -e 's/TMP/DISPLAY="FALSE"/g' YOUR_FILE
Zorzi
  • 718
  • 4
  • 9
  • Thank you for the answer, This works but the requirement is different, Sorry that I haven't made the question more clear. The requirement is to match and replace only in the occurrence of both lines i.e when 2 – Jerald Sabu M Apr 18 '20 at 07:11
1

With -z the newlines will be handled as normal characters:

sed -zr 's/(SYN DISPLAY=)("TRUE")([^\n]*)\n([^\n]*)SYN DISPLAY=("FALSE")/\1\5\3\n\4\1\2/g' inputfile

In your example the remembered strings are:

\1=SYN DISPLAY=
\2="TRUE"
\3= SEARCH="TRUE" CLASSIFY="TRUE">Appels</SYN>
\4= <
\5="FALSE"

Both lines are used for the match, a single line will not be changed.

Walter A
  • 19,067
  • 2
  • 23
  • 43
  • Thank you so much for the answer and explanation. This works as expected. One question, Is it possible to replace the group number (1 or 2, etc ) with some other string instead? – Jerald Sabu M Apr 19 '20 at 21:07
  • @JeraldSabuM I do not understand your question. `\1` should be used when you want to get the first remembered group, but you are not obliged to use that string. You are allowed to write `sed -zr 's/(SYN DISPLAY=)("TRUE")([^\n]*)\n([^\n]*)SYN DISPLAY=("FALSE")/syn comment=lowercase display=\5\3\n\4syn comment=otherChange display=\2/g' inputfile` – Walter A Apr 20 '20 at 07:58