I have a string like this one:
#
pap
which basically translates to a \\t#\\n\\tpap
and I want to replace it with:
A GNU sed
solution that doesn't require reading the entire file at once:
sed '/^\t#$/ {n;/^\tpap$/a\\tpython'$'\n''}' file
/^\t#$/
matches comment-only lines (matching \t#
exactly), in which case (only) the entire {...}
expression is executed:
n
loads and prints the next line./^\tpap/
matches that next line against \tpap
exactly.a\\tpython
will then output \n\tpython
before the following line is read - note that the spliced-in newline ($'\n'
) is required to signal the end of the text passed to the a
command (you can alternatively use multiple -e
options).(As an aside: with BSD sed
(OS X), it gets cumbersome, because
\n
and \t
aren't directly supported and must be spliced in as ANSI C-quoted literals.Leading whitespace is invariably stripped from the text argument to the a
command, so a substitution approach must be used: s//&\'$'\n\t'python'/
replaces the pap
line with itself plus the line to append:
sed '/^'$'\t''#$/ {n; /^'$'\t''pap$/ s//&\'$'\n\t'python'/;}' file
)
An awk
solution (POSIX-compliant) that also doesn't require reading the entire file at once:
awk '{print} /^\t#$/ {f=1;next} f && /^\tpap$/ {print "\tpython"} {f=0}' file
{print}
: prints every input line/^\t#$/ {f=1;next}
: sets flag f
(for 'found') to 1
if a comment-only line (matching \t#
exactly) is found and moves on to the next line.f && /^\tpap$/ {print "\tpython"}
: if a line is preceded by a comment line and matches \tpap
exactly, outputs extra line \tpython
.{f=0}
: resets the flag that indicates a comment-only line.This might work for you (GNU sed):
sed '/^\t#$/{n;/^\tpap$/{p;s//\tpython/}}' file
If a line contains only \t#
print it, then if the next line contains only \tpap
print it too, then replace that line with \tpython
and print that.
try this line with gawk:
awk -v RS="\0" -v ORS="" '{gsub(/\t#\n\tpap/,"yourNEwString")}7' file
if you want to let sed
handle new lines, you have to read the whole file first:
sed ':a;N;$!ba;s/\t#\n\tpap/NewString/g' file
A couple of pure bash
solutions:
in=$'\t#\n\tpap\n' # input string
echo "${in/$'\t#\n\tpap\n'/$'\t#\n\tpap\n\tpython\n'}"
pap
is followed by \n
, whereas no assumption is made about what precedes \t#
, potentially resulting in false positives.\t#\n\tpap
is always enclosed in \n
, echo "${in/$'\n\t#\n\tpap\n'/$'\n\t#\n\tpap\n\tpython\n'}"
would work robustly; otherwise, see below.=~
operator for regex matching:The =~
operator supports extended regular expressions on the right-hand side and thus allows more flexible and robust matching:
in=$'\t#\n\tpap' # input string
# Search string and string to append after.
search=$'\t#\n\tpap'
append=$'\n\tpython'
out=$in # Initialize output string to input string.
if [[ $in =~ ^(.*$'\n')?("$search")($'\n'.*)?$ ]]; then # perform regex matching
out=${out/$search/$search$append} # replace match with match + appendage
fi
echo "$out"