How to add new line using sed on MacOS? - sed

I wanted to add a new line between </a> and <a><a>
</a><a><a>
</a>
<a><a>
I did this
sed 's#</a><a><a>#</a>\n<a><a>#g' filename but it didn't work.

Powered by mac in two Interpretation:
echo foo | sed 's/f/f\'$'\n/'
echo foo | gsed 's/f/f\n/g'

Some seds, notably Mac / BSD, don't interpret \n as a newline, you need to use an actual newline, preceded by a backslash:
$ echo foo | sed 's/f/f\n/'
fnoo
$ echo foo | sed 's/f/f\
> /'
f
oo
$
Or you can use:
echo foo | sed $'s/f/f\\\n/'

...or you just pound on it! worked for me on insert on mac / osx:
sed "2 i \\\n${TEXT}\n\n" -i ${FILE_PATH_NAME}
sed "2 i \\\nSomeText\n\n" -i textfile.txt

Related

How to replace only last match in a line with sed?

With sed, I can replace the first match in a line using
sed 's/pattern/replacement/'
And all matches using
sed 's/pattern/replacement/g'
How do I replace only the last match, regardless of how many matches there are before it?
Copy pasting from something I've posted elsewhere:
$ # replacing last occurrence
$ # can also use sed -E 's/:([^:]*)$/-\1/'
$ echo 'foo:123:bar:baz' | sed -E 's/(.*):/\1-/'
foo:123:bar-baz
$ echo '456:foo:123:bar:789:baz' | sed -E 's/(.*):/\1-/'
456:foo:123:bar:789-baz
$ echo 'foo and bar and baz land good' | sed -E 's/(.*)and/\1XYZ/'
foo and bar and baz lXYZ good
$ # use word boundaries as necessary - GNU sed
$ echo 'foo and bar and baz land good' | sed -E 's/(.*)\band\b/\1XYZ/'
foo and bar XYZ baz land good
$ # replacing last but one
$ echo 'foo:123:bar:baz' | sed -E 's/(.*):(.*:)/\1-\2/'
foo:123-bar:baz
$ echo '456:foo:123:bar:789:baz' | sed -E 's/(.*):(.*:)/\1-\2/'
456:foo:123:bar-789:baz
$ # replacing last but two
$ echo '456:foo:123:bar:789:baz' | sed -E 's/(.*):((.*:){2})/\1-\2/'
456:foo:123-bar:789:baz
$ # replacing last but three
$ echo '456:foo:123:bar:789:baz' | sed -E 's/(.*):((.*:){3})/\1-\2/'
456:foo-123:bar:789:baz
Further Reading:
Buggy behavior if word boundaries is used inside a group with quanitifiers - for example: echo 'it line with it here sit too' | sed -E 's/with(.*\bit\b){2}/XYZ/' fails
Greedy vs. Reluctant vs. Possessive Quantifiers
Reference - What does this regex mean?
sed manual: Back-references and Subexpressions
This might work for you (GNU sed):
sed 's/\(.*\)pattern/\1replacement/' file
Use greed to swallow up the pattern space and then regexp engine will step back through the line and find the first match i.e. the last match.
A fun way to do this, is to use rev to reverse the characters of each line and write your sed replacement backwards.
rev input_file | sed 's/nrettap/tnemecalper/' | rev

How to find and replace all percent, plus, and pipe signs?

I have a document containing many percent, plus, and pipe signs. I want to replace them with a code, for use in TeX.
% becomes \textpercent.
+ becomes \textplus.
| becomes \textbar.
This is the code I am using, but it does not work:
sed -i "s/\%/\\\textpercent /g" ./file.txt
sed -i "s/|/\\\textbar /g" ./file.txt
sed -i "s/\+/\\\textplus /g" ./file.txt
How can I replace these symbols with this code?
Test script:
#!/bin/bash
cat << 'EOF' > testfile.txt
1+2+3=6
12 is 50% of 24
The pipe character '|' looks like a vertical line.
EOF
sed -i -r 's/%/\\textpercent /g;s/[+]/\\textplus /g;s/[|]/\\textbar /g' testfile.txt
cat testfile.txt
Output:
1\textplus 2\textplus 3=6
12 is 50\textpercent of 24
The pipe character '\textbar ' looks like a vertical line.
This was already suggested in a similar way by #tripleee, and I see no reason why it should not work. As you can see, my platform uses the very same version of GNU sed as yours. The only difference to #tripleee's version is that I use the extended regex mode, so I have to either escape the pipe and the plus or put it into a character class with [].
nawk '{sub(/%/,"\\textpercent");sub(/\+/,"\\textplus");sub(/\|/,"\\textpipe"); print}' file
Tested below:
> echo "% + |" | nawk '{sub(/%/,"\\textpercent");sub(/\+/,"\\textplus");sub(/\|/,"\\textpipe"); print}'
\textpercent \textplus \textpipe
Use single quotes:
$ cat in.txt
foo % bar
foo + bar
foo | bar
$ sed -e 's/%/\\textpercent /g' -e 's/\+/\\textplus /g' -e 's/|/\\textbar /g' < in.txt
foo \textpercent bar
foo \textplus bar
foo \textbar bar

Trim text using sed

How do I remove the first and the last quotes?
echo "\"test\"" | sed 's/"//' | sed 's/"$//'
The above is working as expected, But I guess there must be a better way.
You can combine the sed calls into one:
echo "\"test\"" | sed 's/"//;s/"$//'
The command you posted will remove the first quote even if it's not at the beginning of the line. If you want to make sure that it's only done if it is at the beginning, then you can anchor it like this:
echo "\"test\"" | sed 's/^"//;s/"$//'
Some versions of sed don't like multiple commands separated by semicolons. For them you can do this (it also works in the ones that accept semicolons):
echo "\"test\"" | sed -e 's/^"//' -e 's/"$//'
Maybe you prefer something like this:
echo '"test"' | sed 's/^"\(.*\)"$/\1/'
if you are sure there are no other quotes besides the first and last, just use /g modifier
$ echo "\"test\"" | sed 's/"//g'
test
If you have Ruby(1.9+)
$ echo $s
blah"te"st"test
$ echo $s | ruby -e 's=gets.split("\"");print "#{s[0]}#{s[1..-2].join("\"")+s[-1]}"'
blahte"sttest
Note the 2nd example the first and last quotes which may not be exactly at the first and last positions.
example with more quotes
$ s='bl"ah"te"st"tes"t'
$ echo $s | ruby -e 's=gets.split("\"");print "#{s[0]}#{s[1..-2].join("\"")+s[-1]}"'
blah"te"st"test

sed and special char

im trying the following sed command, but i have no luck with special chars:
echo "x#asdf" | sed "s/\([^-]\)#/\1\n/g"
x
asdf
but if i use some special char in test.txt
echo "ä#asdf" | sed "s/\([^-]\)#/\1\n/g"
ä#asdf
why ?
this works:
echo "ü#asdf" | sed "s/ü/-/g"
-#asdf
but this doesnt:
echo "ü#asdf" | sed "s/[ü]/-/g"
ü#asdf
I'm not sure about this, because your sed commands work ok for me (gnu sed 4.1.5), but try invoking sed this way:
$ LANG=de_DE.UTF-8 sed ...
See this post for more information: Why does sed fail with International characters and how to fix?.
If this doesn't work, it may help to upgrade to gnu sed 4.2, if you can. The NEWS file says "multibyte processing fixed" for 4.2 but does not go into further detail.

Is there a way to use regexes in sed without having to put backslash everywhere?

To use regex syntax in sed, you have to put in \ before (, {, etc. to use them as special characters. For example:
~ > echo 123 | sed 's/[0-9]{2}/x/'
123
vs.
~ > echo 123 | sed 's/[0-9]\{2\}/x/'
x3
This is the reverse of what I'm used to. Is there any way to make characters have special meanings by default?
Try:
echo 123 | sed -r 's/[0-9]{2}/x/'
If your sed doesn't have -r:
echo 123 | perl -pe 's/[0-9]{2}/x/'