I found line sed 's~ ~~g' in a shell script on a Linux system. What is this ~?
- 1,156
- 3
- 12
- 25
- 309
- 3
- 6
-
6In this case tilda is delimiter. Did you read `sed` man page? – Romeo Ninov May 11 '18 at 07:54
-
see also: https://stackoverflow.com/questions/5864146/how-to-use-different-delimiters-for-sed-substitute-command – Sundeep May 11 '18 at 08:42
-
24@RomeoNinov s~tilda~tilde~ – Konrad Rudolph May 11 '18 at 10:36
-
7Not sure this qualifies for closure under "requests for learning *materials*" as the question is very simply & directly: `what is this ~ doing here in this sed script?` – Jeff Schaller May 11 '18 at 10:58
-
1@RomeoNinov - a rhetorical question, I suppose... the obvious answer is _No, they did not_. Plenty of people who didn't read it, judging by the number of upvotes here... – don_crissti May 11 '18 at 13:35
-
@don_crissti, my bad, was not exact duplicate, but one of the reasons needed to use different delimiter as pointed in 4th paragraph of [**Gilles**'s answer](https://unix.stackexchange.com/a/33005/72456) there as well as given answers pointing the same. – αғsнιη May 11 '18 at 13:45
-
1@muru - yeah... there's a question like this for every possible character (e.g. [sed exclamation marks](https://unix.stackexchange.com/q/307416/22142) etc) yet almost no one bothers searching... U&L is slowly turning into a new SO... – don_crissti May 14 '18 at 13:03
2 Answers
It's an alternative delimiter for the sed substitute (s) command. Usually, the slash is used, as in s/pattern/replacement/, but sed allows for almost any character to be used.
The main reason for using another delimiter than / in the sed substitution expression is when the expression will act on literal / characters.
For example, to substitute the path /some/path/here with /other/path/now, one may do
s/\/some\/path\/here/\/other\/path\/now/
This suffers from what's usually referred to as "leaning toothpick syndrome", which means it's hard to read and to properly maintain.
Instead, we are allowed to use another expression delimiter:
s#/some/path/here#/other/path/now#
Using ~ is just another example of a valid substitution expression delimiter.
Your expression
s~ ~~g
is the same as
s/ //g
and will remove all spaces from the input. In this case, using another delimiter than / is not needed at all since neither pattern nor replacement contains /.
Another way of doing the same thing is
tr -d ' ' <infile >outfile
- 320,670
- 36
- 633
- 936
It's a substitution delimiter. The most often used delimiter is a forward slash /. But sed can use any character as a delimiter - it will automatically use the character following the s as a delimiter:
sed 's@ @@g'
sed 's+ ++g'
sed 's\ \\g'
sed 's* **g'
Also it is possible to use space as delimiter:
echo "foo" | sed 's foo bar g'
Other delimiters than / are most often used when you have many slashes in your command in the syntax is getting confusing. Consider this case where we want to convert multiple spaces to just one space character: Instead of
echo " a b c " | sed 's/\s\{1,\}/ /g'
you can run
echo " a b c " | sed 's~\s\{1,\}~ ~g'
which is more clear.
- 2,423
- 6
- 22
- 47
-
2Backslashes only work in some implementations of `sed`, e.g. GNU `sed`. – Kusalananda May 11 '18 at 08:07
-
1_Any character other than backslash or newline can be used instead of a slash to delimit the BRE and the replacement_ ([reference](http://pubs.opengroup.org/onlinepubs/009604599/utilities/sed.html)) – fedorqui May 11 '18 at 08:42
-
@fedorqui Why should they not be used? It's working in `sed 4.4`, so you can use it. – manifestor May 11 '18 at 08:45
-
2This is what POSIX says, it is not me :) Having it run in some implementations (like @Kusalananda mentions) is fine, only that you have to be aware that it won't be the case in all of them – fedorqui May 11 '18 at 08:52
-
yes, but he did not demand that the answer should be POSIX compliant. – manifestor May 11 '18 at 08:55
-
1Of course :) He did not demand any explanation on extra delimiters, but since you kindly explained that, showing the whole picture will be even more useful! – fedorqui May 11 '18 at 09:00
-
2It's even possible to use the space itself as the delimiter, so long as it's escaped in the pattern: `sed -e 's \ g'`. (Don't copy & paste that: I've had to use non-breaking spaces to prevent the site from messing it up.) But don't ever write that in code that's meant to remain readable even a minute later. – hvd May 11 '18 at 10:25
-
1@hvd how about `sed -e 'ss ssg'` (or similarly, `sed -e 'sg ggg'`) XD – Doktor J May 11 '18 at 14:12
-
Note that converting multiple spaces to just one can be done in an easier manner with `tr -s ' '`, which stands for _squeezes_. – fedorqui May 16 '18 at 10:15