Change a String in a File with Sed

sed search and replace strings containing /

Don't escape the backslashes; you'll confuse yourself. Use a different symbol after the s command that doesn't appear in the text (I'm using % in the example below):

line_old='myparam /path/to/a argB=/path/to/B xo'
line_new='myparam /path/to/c argB=/path/to/D xo'
sed -i "s%$line_old%$line_new%g" /etc/myconfig

Also, enclose the whole string in double quotes; using single quotes means that sed sees $line (in the original) instead of the expanded value. Inside single quotes, there is no expansion and there are no metacharacters. If your text can contain almost any plain text character, use a control character (e.g. control-A or control-G) as the delimiter.

Note that the use of -i here mirrors what is in the question, but that assumes the use of GNU sed. BSD sed (found on Mac OS X too) requires a suffix. You can use sed -i '' … to replace in situ; that does not work with GNU sed. To be portable between the two, use -i.bak; that will work with both — but gives you a backup file that you'll probably want to delete. Other Unix platforms (e.g. AIX, HP-UX, Solaris) may have variants of sed that do not support -i at all. It is not required by the POSIX specification for sed.

Linux/Unix Replacing a pattern in a string and saving to a new file with sed

You can try this sed command

sed 's/,\(.*china\)/,Tomas_proxy.lt\/\1/' FileName

or

sed 's/,\(.*china\)/,Tomas_proxy.lt\/\1/' FileName > NewFile

or

sed  -i.bak 's/,\(.*china\)/,Tomas_proxy.lt\/\1/' FileName 

how to use sed to replace a string in a file with a shell variable

It seems to be that you're trying a combination of piping to sed and using a file. The following will work perfectly fine,

sed -i -e "s/{VERSION}/${VERSION}/" -e "s/{DISTRO}/${DISTRO}/" ${OUT_CAT}

You don't need to escape the $, and you don't pipe into sed since you're using -i to modify the file in-place. You also need to use -e for each expression when their are more than one.

EDIT: Here is the bit in the sed manual pages that gives the indication of the issue with -e option (emphasis mine),

If no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret. All
remaining arguments are names of input files
; if no input files are
specified, then the standard input is read.

Sed command to change a string at only desired place

Is there any way to replace the string using a WHERE clause so I can replace the string only where I want?

sed does not have SQL-style WHERE clauses, but commands can have "addresses" that define subsets of input lines to operate upon. These can take several forms. Regular expressions are perhaps the most common, but there are also line numbers, and a couple of special forms. You can also have inclusive ranges built from simple addresses. An address range would be a reasonably good way to address the problem you present.

For example,

sed -i '/^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/ s/dependsOn: Build/dependsOn: Test/' input

Explanation:

  • The -i command-line flag tells sed to work "in-place", which really means that it will replace the original file with one containing sed's output.

  • The /^\s*-\s*stage:\s*Moto_Dev/,/^\s*-/ is a range address, consisting of a regex for the range start (/^\s*-\s*stage:\s*MotoDev/) and one for the range end (/^\s*-/).

    • /^\s*-\s*stage:\s*Moto_Dev/ matches the beginning of the section in which you want the change to be made, with some flexibility around the exact amount of whitespace at certain positions. For brevity and clarity, it uses \s to represent a single space or tab character. That is a GNU extension, but if you cannot depend on GNU sed then there are other ways to express the same thing.
    • /^\s*-/ matches the beginning of the next section, as you have presented the input. It could be made more specific if it were necessary to be more selective.
      The range includes its endpoints, but that does not appear to be a problem for the task at hand.
  • There is only one such range in the input presented, and that range contains the line you want to modify. The specified substitution, s/dependsOn: Build/dependsOn: Test/, is performed on each line in the range, but only the one contains a match to be replaced. All others in the range will be unaffected.

  • No commands at all are specified for lines outside the range, so they too will be unaffected.


You also asked,

I stored the desired piece of code in a variable. Can I use that
variable in a sed command? For example,

sed -i "s/condition: succeeded('Fair_PreProd')/condition: succeeded('Fair_UAT')/g" $folder_path/$file_name

sed does not expand shell-style parameter references, but you don't need it to do. The variable references in that command are expanded by the shell itself, before it executes the resulting command, so

  • yes, you may use them, and
  • it's not a question of using shell variables with sed in particular.

How to replace strings of a text file based on two list using sed

With GNU sed you can match beginning and ending of a word with \< \>. You may first generate a sed script from your input then pass it to sed. There have to be no special characters in input.

script=$(
paste OLD_SM.list NEW_SM.list |
sed 's/\(.*\)\t\(.*\)/s~\\<\1\\>~\2~g/'
)
sed -i "/^#CHROM/{ $script }" file.

The s/[[:space:]]${OLD_SM}$ - the $ matches end of line, so it's never going to work. You may do s/\(^\|[[:space:]]\)$OLD_SM\([[:space:]]\|$\)/\1$NEW_SM\2/ - match beginning of a line or space, then the word, then space or ending of line, and then substitute for backreference. Topics to research: regex and backreferences in sed.

How to find and replace string in a file WITHOUT sed

You can use awk for find and replace as well. Here's a resource with more detail..

For example, your makefile command could be replaced with:

omz-theme:
awk -v var="ZSH_THEME=$(echo THEME)" '{sub(/^ZSH_THEME=.*$/, var); print}' $(HOME)/.zshrc

You could use this to overwrite the existing $(HOME)/.zshrc file using redirection:

omz-theme:
awk -v var="ZSH_THEME=$(echo THEME)" '{sub(/^ZSH_THEME=.*$/, var); print}' $(HOME)/.zshrc > $(HOME)/.zshrc

Alternately, you could check the OS using OSTYPE and then use the correct sed syntax for BSD and GNU:

omz-theme:
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
sed -i 's/ZSH_THEME=".*"/ZSH_THEME="$(THEME)"/g' $(HOME)/.zshrc
else
sed -i '' 's/ZSH_THEME=".*"/ZSH_THEME="$(THEME)"/g' $(HOME)/.zshrc
fi

(note: I didn't test the above, but you get the idea)



Related Topics



Leave a reply



Submit