1

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.

1

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

$'\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.)

  • use $'\r\n', perl only see a newline, and will represent it as '\n'. – cuonglm Sep 13 '14 at 6:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.