Change specific part of a line in a file with sed - bash

I have a line in a autoexec.py file that I want another script to be able to modify:
kodi.executebuiltin("PlayMedia(/path/to/file)")
I was thinking of using sed to override the value within PlayMedia() depending on certain conditions.
Can sed be used to only touch and overwrite the parts between the PlayMedia() brackets and nothing else? Or is further processing/regex needed?

You could use sed. The below code will replace the chars present inside the brackets following PlayMedia string with foo.
sed 's/\b\(PlayMedia\)([^)]*)/\1(foo)/g' file
If the string you want to replace is a path, you must use a different sed delimiter because filepath may contain forward slashes.
sed 's~\b\(PlayMedia\)([^)]*)~\1(foo)~g' file
Example:
$ echo 'kodi.executebuiltin("PlayMedia(/path/to/file)")' | sed 's/\b\(PlayMedia\)([^)]*)/\1(foo)/g'
kodi.executebuiltin("PlayMedia(foo)")

Related

Remove prefix of each line in a file and output to another file using sed

I have a source code file in which comments are prefixed with // (ie. double slashes and an empty space), I want to convert the source code into a document so I tried to cat file.c and pipe it to sed, the thinking is to replace "double slash and a space" if a line starts with it, with empty string, but it looks like the slash has some special meaning in sed, so what's the best way of constructing the sed arguments?
Thanks!
If you want to remove the special meaning of / from sed then following may help you in same.
sed 's/^\/\/ //g' Input_file
So I am escaping / here by using \ before it, so it will be taken as a literal character rather than it's special meaning in code. Also if you are happy with above command's result then use -i to save the changes in Input_file itself. Hope this helps.
The slash only has meaning if you allow it.
sed 's#^// +##' < file.c

using variables in regex?

Part of a shell script that I am creating takes a plain text list of files...
11111.jpg
22222.jpg
33333.jpg
...and appends a user-defined prefix that is stored in a variable to create a list of paths that looks like this:
user/defined/prefix/11111.jpg
user/defined/prefix/22222.jpg
user/defined/prefix/33333.jpg
I am attempting to use sed to add the prefix in this manner:
sed -e 's/^/prefix/' oldFile > newFile.new
The variable is getting assigned correctly:
echo $selectedPrefix
user/defined/prefix
Put no combinations of single quotes, double quotes of whatever seem to get sed to use the ACTUAL value of the variable instead of just the variable name.
sed -e 's/^/$selectedPrefix/' oldFile > newFile.new
Yields:
$selectedPrefix11111.jpg
$selectedPrefix22222.jpg
$selectedPrefix33333.jpg
Help! I'm sure the solution is simple but I feel like I've tried everything....
As mentionned by Cyrus, you need to used " (double quote) instead ' (single quote) if you want the variable replacement because single quoted string are interpreted literally so it doesn't see $selectedPrefix as a variable but as the string value of $selectedPrefic hence what you saw.
Since you are working with paths in you sed, you are correct in assuming that you should use a different separator for your sed comment. I usually prefer using | but ~ would also work.
so basically you could have:
sed -e "s~^~$selectedPrefix~" oldFile > newFile.new
This code would solve your problem:
selectedPrefixEscaped="$(echo "$selectedPrefix" | sed 's/\//\\\//g')" && sed -e "s/^/$selectedPrefixEscaped/" oldFile > newFile.new
Just using a different delimiter on sed would leave you open to problems when (if) the path contains the new delimiter (ex.: /folder/folder#5/file.txt would be problematic if using # as sed delimiter).

Replace content in a file or line matching a regular expression using SED

How to replace a line / part of a line in a file using SED command?
search_text_1_server=value.env_1.path_to_file
search_text_2_server=value.env_1.path_to_file
search_text_3_server=value.env_1.path_to_file
some_other_key=value.env_1.another_path
Now I want a sed command to find the lines which match the regular expression search_text_{any}_server and then replace env_1 with env_2
Found the regular expression to find the required lines.
^search_text_[a-z_]\*_server.*$
Now how to add the SED syntax to replace
PS : I am not an expert in shell
Your regex is close. You can use:
sed -E 's/^(search_text_[a-z_]*_server=.*)env_1\./\1env_2\./' file
search_text_1_server=value.env_2.path_to_file
search_text_2_server=value.env_2.path_to_file
search_text_3_server=value.env_2.path_to_file
some_other_key=value.env_1.another_path
Assuming country code to be two alphabets, you could do
sed -Ei 's/(search_text_[a-z]{2}_server=value\.)env_1/\1env_2/' file
should do it.
What's happening here
[a-z]{2} checks for two alphabets which make a country code
sed s command is for substitution -> s/pattern/replacement
() selects the matched regex pattern for reuse, Note \1 for reuse
-i is the inplace edit option of sed which makes changes permanent in the file

How to remove line matching specific pattern from a file

I know sed could be used to delete specific line from file:
sed -i "/pattern/d" file
While the pattern of my case includes slash, like /var/log,
So I know I need escape: sed -i "/\/tmp\/dir/d" file
However, for my case, the pattern is dynamic, should be a variable
in a shell file, so I have to convert the variable value to replace
"/" with "\\/", then got this:
sed -i "/^${pattern_variable//\\//\\\\\\/}$/d" file
My question is, is there any better implementation which is more readable or simpler? Not only sed, other utility is also acceptable. Is it possible to handle not only slash but also other various symbols, like backslash or # ()?
you can use char other than /:
sed "\#$varHasSlash#d"
example:
kent$ foo="b/c"
kent$ echo "a
ab/cd
e"|sed "\#$foo#d"
a
e

remove absolute path using sed command

I have file which contain following context like
abc...
include /home/user/file.txt'
some text
I need to remove include and also complete path after include.
I have used following command which remove include but did not remove path.
sed -i -r 's#include##g' 'filename'
I am also trying to understand above command but did not understand following thing ( copy paste from somewhere)
i - modify file change
r - read file
s- Need input
g - Need input
Try this,
$ sed '/^include /s/.*//g' file.txt
abc...
some text
It remove all the texts in a line which starts with include. s means substitute. so s/.*//g means replace all the texts with null.g means global. The substitution will be applied globally.
OR
$ sed '/^include /d' file.txt
abc...
some text
d means delete.
It deletes the line which starts with include. To save the changes made(inline edit), your commands should be
sed -i '/^include /s/.*//g' file.txt
sed -i '/^include /d' file.txt
I your case if you just want to delete the second line, you can use:
sed -i '2d' file
If you want to explore something about linux commands then man pages are there for you.
Just go to terminal and type:
man sed
as per your question, The above command without -i will show the file content on terminal by deleting the second line from the input file. However, the input file remains unchanged. To update the original file or to make the changes permanently in the source file, use the -i option.
-i[SUFFIX], --in-place[=SUFFIX] :
edit files in place (makes backup if extension supplied)
-r or --regexp-extended :
option is to use extended regular expressions in the script.
s/regexp/replacement/ :
Attempt to match regexp against the pattern space. If success‐
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
g G : Copy/append hold space to pattern space.
grep -v
This is not about learning sed, but as an alternative (and short) solution, there is:
grep -v '^include' filename_in
Or with output redirection:
grep -v '^include' filename_in > filename_out
-v option for grep inverts matching (hence printing non-matching lines).
For simple deletion that's what I'd use; if you have to modify your path after the include, stick with sed instead.
You can use awk to just delete the line:
awk '/^include/ {next}1' file
sed -i -r 's#include##g' 'filename'
-i: you directly modify the treated file, by default, sed read a file, modify the content via stdout (the original file stay the same).
-r: use of extended regular expression (and not reduce to POSIX limited one).This is not necessary in this case due to simple POSIX compliant action in action list (the s### string).
s#pattern#NewValue#: substitute in current line the pattern (Regular Expression) with "Newvalue" (that also use internal buffer or specific value). The traditionnal form is s/// but in this case, using / in path (pattern or new value) an alternate form is used to avoid to escape all / in pattern or new value
g: is an option of s### that specify change EVERY occurence and not the first (by default)
so here it replace ANY occurence of include by nothing (remove) directly into your file
As per the Avinash Raj solution you got what you want but you want some explaination about some parameter used in sed command
First one is
command: s for substitution
With the sed command the substitute command s changes all occurrences of the regular expression into a new value. A simple example is changing "my" in the "file1" to "yours" in the "file2" file:
sed s/my/yours/ file1 >file2
The character after the s is the delimiter. It is conventionally a slash, because this is what ed, more, and vi use. It can be anything you want, however. If you want to change a pathname that contains a slash - say /usr/local/bin to /common/bin - you could use the backslash to quote the slash:
sed 's/\/usr\/local\/bin/\/common\/bin/' <old >new
/g - Global replacement
Replace all matches, not just the first match.
If you tell it to change a word, it will only change the first occurrence of the word on a line. You may want to make the change on every word on the line instead of the first then add a g after the last delimiter and use the work-around:
Delete with d
Delete the pattern space; immediately start next cycle.
You can delete line by specifying the line number. like
sed '$d' filename.txt
It will remove last line of file
sed '2 d' file.txt
It will delete second line of file.
-i option
This option specifies that files are to be edited in-place. GNU sed does this by creating a temporary file and sending output to this file rather than to the standard output.
To modify file actully you can use -i option without it sed command repressent changes on stdout not actual file. You can take backup of original file before modification by using -i.bak option.
-r option
--regexp-extended
Use extended regular expressions rather than basic regular expressions. Extended regexps are those that egrep accepts; they can be clearer because they usually have less backslashes, but are a GNU extension and hence scripts that use them are not portable.

Resources