Replace only if string exists in current line
Solution
Assuming your input file $target contains the following:
some text mystring some other text
some text mystring a searchstring
just some more text
This command:
sed -i -e '/searchstring/ s/mystring/1/ ; /searchstring/! s/mystring/0/' $target
will change its content to:
some text 0 some other text
some text 1 a searchstring
just some more text
Explanation
The script contains two substitute (s) commands separated by a semicolon.
The substitute command accepts an optional address range that select which lines the substitution should take place.
In this case regexp address was used to select lines containing the searchstring for the first command; and the lines that do not contain the searchstring (note the exclamation mark after the regexp negating the match) for the second one.
Edit
This command will perform better and produce just the same result:
sed -i -e '/searchstring/ s/mystring/1/ ; s/mystring/0/' $target
The point is that commands are executed sequentially and thus if there is still a mystring substring in the current line after the first command finished then there is no searchstring in it for sure.
Kudos to user946850.
Bash creating a string, if string already exists replace it
if there is the few text, it should replace it, if few text is missing, just create it on the first line.
That's an if.
if <file has text>; then <replace text>; else <add text to first line>; fi
or in bash:
file=/usr/local/sbin/.myappenv
if grep -q few "$file"; then
sed 's/few/asd/' "$file"
else
{
echo asd
cat "$file"
} > "$file".tmp
mv "$file".tmp "$file"
fi
How to test if string exists in file with Bash? https://unix.stackexchange.com/questions/99350/how-to-insert-text-before-the-first-line-of-a-file and https://mywiki.wooledge.org/BashGuide/TestsAndConditionals . You might interest yourself in some automation methods, like ansible lineinfile or chezmoi depending on the goal.
Replace a string if a particular substring exists?
sed '/String/ s/My/YOUR/g' input
OR
awk '/String/{gsub(/My/,"YOUR")}1' input
Replace whole string if it contains substring in pandas
You can use str.contains
to mask the rows that contain 'ball' and then overwrite with the new value:
In [71]:
df.loc[df['sport'].str.contains('ball'), 'sport'] = 'ball sport'
df
Out[71]:
name sport
0 Bob tennis
1 Jane ball sport
2 Alice ball sport
To make it case-insensitive pass `case=False:
df.loc[df['sport'].str.contains('ball', case=False), 'sport'] = 'ball sport'
Find/replace within a line only if line does not contain a certain string (awk)
You are incorrectly using the gsub()
function here. The sub()
/gsub()
function return the number of substitutions made and not the modified string. You set the string to modify as the last argument and print it back
awk '{ for(j=1; j<=NF; j++) if ($j ~ "_") print; else { gsub("A","1",$0); print } }'
That said your first command is most efficient/terse way of writing this. Notice you were missing a }
in the OP. It should been written as
awk '!/_/{ gsub("A", "1") }1'
Or use gensub()
available in GNU Awk's that return the modified string that you can use to print
. See more about it on String-Functions of GNU Awk
awk '{ for(j=1; j<=NF; j++) if ($j ~ "_") print; else print gensub(/A/, "1", "g") }'
Replace text in file if previous line matches another text
One way to do it with sed
(tested using macOS's sed and GNU sed), would be this:
replace.sed
#!/usr/bin/env sed -Ef
/FooBarB/,/^FooBar/ {
s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/
}
Here's what it does:
/FooBarB/,/^FooBar/
matches a range of lines where the first line matches the regex/FooBarB/
and the last line matches the regex/^FooBar/
(which is the start of the next "group"). The comma between the two regexes is the syntax for range matching insed
.s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/
— [s]ubstitutes (in the matched range of lines) whatever matches the regex(foo[[:space:]]*=[[:space:]]*).+
with\1new-value
, where\1
references the first capturing group in the search regex. The search regex looks forfoo
followed by optional whitespace, followed by an=
sign, followed again by whitespace and then whatever else is there, which in your case is the old value.
You could do it all in just one line, but I wanted to show a version that's a bit more digestible (as far as sed
goes, in any case):
sed -E '/FooBarA/,/^FooBar/s/(foo[[:space:]]*=[[:space:]]*).+/\1new-value/' temp.md
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 tellssed
to work "in-place", which really means that it will replace the original file with one containingsed
'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 GNUsed
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 ased
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.
Replace whole line containing a string using Sed
You can use the change command to replace the entire line, and the -i
flag to make the changes in-place. For example, using GNU sed:
sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo
Related Topics
What's the Difference Between Event-Driven and Asynchronous? Between Epoll and Aio
How to Delete First Two Lines and Last Four Lines from a Text File with Bash
Macros for Gcc/G++ to Differentiate Linux and MAC Osx
Recursively Find Files with a Specific Extension
What Is Preemption/What Is a Preemtible Kernel? What Is It Good For
Need Explanations for Linux Bash Builtin Exec Command Behavior
Execute a Shell Script Everyday at Specific Time
How Is It Possible That Kill -9 for a Process on Linux Has No Effect
Get First Line of a Shell Command's Output
Split Output of Command by Columns Using Bash
How to Install SQL * Plus Client in Linux
Shell Script Current Directory
Systemd with Multiple Execstart
How to Diff Directories Over Ssh
How to Get Cmake to Use the Default Compiler on System Path