1

I have been using replace-in-file node js utility to replace string values in files. Using this utility as it can be called from bash script. However this time there is requirement to replace next line, if I find the given string in previous line. For example,

<values>
    <field>Namespace__c</field>
    <value xsi:nil="true"/>
</values>

Utility should search Namespace string and if found, it should replace next line i.e.

<value xsi:nil="true"/>

with given value. I tried to do it with regular expression,

module.exports = { 
    from: '/<field>Namespace__c</field>\n<value xsi:nil="true"/>/g', 
    to: '<field>Namespace__c</field>\n<value xsi:type="xsd:string">namespace</value>', 
    files:[ 'path to file/*.md' ], 
    isRegex: true, 

but no success yet. Thanks in advance for help!

3
  • 1
    So, what regex did you try? Please share. Commented Mar 6, 2020 at 11:59
  • Hi Wiktor, so far I have tried this way. module.exports = { from: '/<field>Namespace__c</field>\n<value xsi:nil="true"/>/g', to: '<field>Namespace__c</field>\n<value xsi:type="xsd:string">namespace</value>', files:[ 'path to file/*.md' ], isRegex: true, } Commented Mar 6, 2020 at 13:00
  • 1
    Please add to the question. Commented Mar 6, 2020 at 13:01

1 Answer 1

1

You may use GNU sed:

sed -i '/Namespace/{N;s,\(\n[[:space:]]*\).*,\1<value xsi:type="xsd:string">namespace</value>,}' your_file

See an online demo:

s='<values>
    <field>Namespace__c</field>
    <value xsi:nil="true"/>
</values>'

sed '/Namespace/{N;s,\(\n[[:space:]]*\).*,\1<value xsi:type="xsd:string">namespace</value>,}' <<< "$s"

Result:

<values>
    <field>Namespace__c</field>
    <value xsi:type="xsd:string">namespace</value>
</values>

Details

  • /Namespace/ - match a line that contains Namespace
  • { - if there is a match
    • N; - append a newline to the pattern space and append the next line to it
    • s,\(\n[[:space:]]*\).*,\1<value xsi:type="xsd:string">namespace</value>,: finds and captures into Group 1 a newline and 0+ whitespaces after it, and then matches all the line to the end with .*, and then replaces the match with the text in Group 1 (\1) and the string of your choice
  • } - end of the block.
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks Wiktor. As these values are in XML files, can I pass the path to files in SED command?
@Amit You may, /path/to/files/*.xml?
so the command should look like: sed '/Namespace/{N;s,(\n[[:space:]]*).*,\1<value xsi:type="xsd:string">namespace</value>,}' <<< "path/to/file/*.xml" ?
So the command works but it outputs on the bash itself. Can this command just modify the file itself instead of outputting it on bash?
@Amit Right, -i enforces inline file change, and you only need <<< when you pass a variable containing text, when you need to pass a file path, you do not need <<<.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.