Escaped characters from the command-line

I’ve run into a bit of an issue that I hope you can help with.
I am working on a parser that allows the user to provide a delimiter as
an argument to the script. However, I can not find a way to [elegantly]
handle escaped characters (such as \t and \n).
A simplified example to illustrate:

Using

s = ARGV.shift
puts [‘west’, ‘side’, story’].join(s)

$ ./parse.rb ‘\t’
=> west\tside\tstory

Now, I can do something like:

s = ARGV.shift
sep = s =~ /^\(.)/
when ‘t’
“\t”
when ‘n’
“\n”

else
s
end
end

$ ./parse.rb ‘\t’
=> west side story

But I feel that is probably too brittle. I tried Shellwords, but that
didnt seem to help (although I could have been using it incorrectly).
Any suggestions are welcome.
Thanks.

-j b- wrote:

I am working on a parser that allows the user to provide a delimiter as
an argument to the script. However, I can not find a way to [elegantly]
handle escaped characters (such as \t and \n).
A simplified example to illustrate:

Using

s = ARGV.shift
puts [‘west’, ‘side’, story’].join(s)

$ ./parse.rb ‘\t’
=> west\tside\tstory

It isn’t a Ruby issue. It’s a shell one. You need to find out how it’s
possible, in your shell, to specify those special characters. Are you
using Linux? Bash?

$ echo one\ntwo
onentwo

$echo ‘one\ntwo’
one\ntwo

$echo $‘one\ntwo’
one
two

$echo ‘one
two’
onw
two

$echo “one
two”
onw
two

So there are at least three ways to do \n in bash.

I’m still looking for a more elegant way then the
heavy case statement.
I’ve experimented with a gsub! solution but the way backslashes are
escaped in regular expressions (particularly when reinserting into a
string) has me blocked at the moment.

All you’re looking for is a cool one-liner? Here’s one:

s.gsub!(/(\[ntr])/) { eval %/"#$1"/ }

It replaces any \n and \t sequence by it’s character. You can even
enhance the regexp to support \x sequences as well:

s.gsub!(/(\([ntr]|x\d+))/) { eval %/"#$1"/ }

Albert S. wrote:

-j b- wrote:

I am working on a parser that allows the user to provide a delimiter as
an argument to the script. However, I can not find a way to [elegantly]
handle escaped characters (such as \t and \n).
A simplified example to illustrate:

Using

s = ARGV.shift
puts [‘west’, ‘side’, story’].join(s)

$ ./parse.rb ‘\t’
=> west\tside\tstory

It isn’t a Ruby issue. It’s a shell one. You need to find out how it’s
possible, in your shell, to specify those special characters. Are you
using Linux? Bash?

Yes. Yes. But the idea is that it shouldnt matter.

So there are at least three ways to do \n in bash.

I know that it possible, from a user standpoint, to input a special
character in multiple ways. My concern is that I dont want to force that
restriction on the user. For example, the utility tr will accept ‘\t’ as
a single character; I find this ultimately more useful than tr ‘^v[tab]’
’ ’ (or any of the above mentioned methods).
If it is a shell issue then I am forced to modify the arguments
accordingly. However, I’m still looking for a more elegant way then the
heavy case statement.
I’ve experimented with a gsub! solution but the way backslashes are
escaped in regular expressions (particularly when reinserting into a
string) has me blocked at the moment.

Thanks.

j

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

  • -j b- wrote:

|> It isn’t a Ruby issue. It’s a shell one. You need to find out how it’s
|> possible, in your shell, to specify those special characters. Are you
|> using Linux? Bash?
|
| Yes. Yes. But the idea is that it shouldnt matter.

Have fun rewriting the *NIX shells, cmd.exe, and, possibly, PowerShell,
too.


Phillip G.
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com

Use statement labels that mean something.
~ - The Elements of Programming Style (Kernighan & Plaugher)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgguakACgkQbtAgaoJTgL/PPwCgplzxuF3E608P8jtSCWukpA4o
zlgAn1oQVkLOnSLkmMtwrhMWCGuNro0V
=iHkS
-----END PGP SIGNATURE-----