3

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

3

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
4
  • I don't understand. Where did the \r go and why?
    – test
    Sep 13, 2014 at 4:16
  • @test: Because perl convert \n and your OS's native newline, see: perldoc.perl.org/perlrebackslash.html
    – cuonglm
    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.
    – test
    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.
    – cuonglm
    Sep 13, 2014 at 6:33
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'.
    – cuonglm
    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' Jan 20, 2021 at 21:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .