6

I don't use bash often but I recall in the past to pass a tab or newline on the command line I would have to escape the character using the special $ character before a single quoted string. Like $'\t', $'\n', etc. I had read about quotes and escaping in the bash manual.

What I want to know is when it's appropriate to use an ANSI C style escape. For example I was working with a regex in grep and it appeared I needed an ANSI C style escape for a newline. Then I switched to perl and it seemed I didn't.

Take for example my recent question on stackoverflow about a perl regex that didn't work. Here's the regex I was using:

echo -e -n "ab\r\ncd" | perl -w -e $'binmode STDIN;undef $/;$_ = <>;if(/ab\r\ncd/){print "test"}'

It turns out that is actually incorrect because I gave the string ANSI C style escape by using $. I just don't understand when I'm supposed to prepend the dollar sign and when I'm not.

2 Answers 2

5

You use $'...' when you want escape sequences to be interpreted by the shell.

$ echo 'a\nb'
a\nb

$ echo $'a\nb'
a
b

In perl, -e option get a string. If you use $'...', the escape sequences in string are interpreted before passing to perl. In your case, \r had gone and never passed to perl.

With $'...':

$ perl -MO=Deparse -we $'binmode STDIN;undef $/;$_ = <>;if(/ab\r\ncd/){print "test"}'
BEGIN { $^W = 1; }
binmode STDIN;
undef $/;
$_ = <ARGV>;
if (/ab\ncd/) {
    print 'test';
}
-e syntax OK

Without it:

$ perl -MO=Deparse -we 'binmode STDIN;undef $/;$_ = <>;if(/ab\r\ncd/){print "test"}'
BEGIN { $^W = 1; }
binmode STDIN;
undef $/;
$_ = <ARGV>;
if (/ab\r\ncd/) {
    print 'test';
}
-e syntax OK
5
  • I don't understand. Where did the \r go and why? Commented Sep 13, 2014 at 4:16
  • @test: Because perl convert \n and your OS's native newline, see: perldoc.perl.org/perlrebackslash.html Commented Sep 13, 2014 at 4:37
  • 1
    Well it is hard to understand you but I think what you mean is \r\n is converted to \n by perl. I read that webpage but it only says the conversion is "reading from or writing to text files." However I assume that because perl receives the \r\n as an actual carriage return and linefeed when using $, and not literally the characters backslash-r-backslash-n as when not using $, that it converts that to the linefeed character which is literally backslash-n. Commented Sep 13, 2014 at 6:10
  • @test: $'\r\n' produces a newline. perl read input, it saw a newline, and since when you're in Linux, perl represent a newline with '\n'. When you used '\r\n', perl saw them as a escape sequence literal. Commented Sep 13, 2014 at 6:33
  • it looks like echo $'a\nb' is same as echo -e 'a\nb' ? Commented Dec 23, 2024 at 18:01
2

$'\n' is basically the same as typing Enter.

So in your Perl example, it turns into*

  if(/ab
cd/)

Which isn't what you wanted.

Reasons I can think of to use $'...':

  • You want to put a single quote inside a single-quote delimited string, e.g. logger $'Can\'t open file'
  • To make non-printable characters clearer, e.g. $'a\tb' rather than 'a<TAB character>b'

(Not sure if \r\n is treated as equivalent to \n or if Perl sees carriage return + newline, but in either case, it's not it what you wanted.)

2
  • use $'\r\n', perl only see a newline, and will represent it as '\n'. Commented Sep 13, 2014 at 6:35
  • Another reason: when I use youtube-dl I sometimes get video files with newlines in them and removing them is a nightmare without $'\n' Commented Jan 20, 2021 at 21:49

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.