I am going to hell [entries|reading|network|archive]
simont

[ userinfo | dreamwidth userinfo ]
[ archive | journal archive ]

Wed 2004-11-10 14:16
I am going to hell

If you thought my previous bash alias hacks were evil, don't even read this one.

Given these definitions …

echo-literally-helper() {
str="`history 1 | perl -pe 's/^ *[0-9]+ +[^ ]+ //'`"
echo "$str"
}
alias echo-literally='echo-literally-helper #'

… the alias echo-literally will now pass its completely uninterpreted command line to the shell function echo-literally-helper. My previous magic-alias mechanism allowed you to prevent or fiddle with wildcard expansion, to alter the values of environment variables and one or two other useful things, but this is an order of magnitude more powerful:

$ echo-literally a; b; c
a; b; c
$ echo-literally a
a
$ echo-literally hello, world > thingy
hello, world > thingy
$ echo-literally ooh # this is a comment
ooh # this is a comment

Of course, this technique isn't limited to printing the command line string verbatim. The shell function gets hold of the text as a string variable, and can process it in any way it sees fit; so you could feed it back to the shell argument parsing if you really wanted (perhaps after modifying some settings which you wouldn't be able to modify using the other mechanism), or have it parsed by a different shell, or do whatever you like with it.

And just like my previous magic-aliases trick, there are limitations. This monstrosity only works when typed at an interactive command line, since otherwise the command doesn't find its way into the history list to be recovered; and also it will break down if you precede it on the line with any other command.

But even so, it's pretty cool, in a genuinely horrifying sort of way. I developed it for my colleague Charlie, who wanted it for use in an rsh-like sort of mechanism (having to quote the complex command line you're passing to the server can be a real pain). I wonder if there are any other particularly fun uses for it.

LinkReply
[identity profile] arnhem.livejournal.comWed 2004-11-10 15:01
You can surely fix the "preceded on the line with any other command" problem by being more specific in the perl regexp match (looking for the first instance of " echo-literally " on the line?)
Link Reply to this | Thread
[personal profile] simontWed 2004-11-10 15:05
That'd help, although it could still be fooled. 90% solutions are easy; what would be interesting would be a 100% one. I'm trying to think of ways to pull the command line back out of the history list and feed it back into the bash parser, but I don't think there's any way to run the bash parser without bash immediately executing the result, and that's definitely unacceptable.
Link Reply to this | Parent | Thread
[identity profile] arnhem.livejournal.comWed 2004-11-10 20:45
Yes. "echo echo-literally ; echo-literally foo; bar; baz" being the obvious problem case.

It all gets a bit mucky; because you're explicitly breaking the parse of the command line, you have to make rather arbitrary decisions about whether to be greedy or not, given something like:
echo `echo-literally foo; bar; baz` ; echo `foo bar`
or
echo $(echo-literally foo; bar; baz) $(echo foo; bar; baz)
Link Reply to this | Parent | Thread
[personal profile] simontWed 2004-11-10 22:36
And worse still, once you've got two of those $(...) constructions on a single line, there's no way for the execution of either one to know which of them is meant. I can't see any possible way to make
echo $(echo-literally a;b;c) $(echo-literally d;e;f)
work at all.
Link Reply to this | Parent
[identity profile] fluffyrichard.livejournal.comWed 2004-11-10 15:17
Gstreamer pipeline definitions spring to mind.

There is a command line tool (gst-launch) to set up a gstreamer pipeline, which currently uses !'s instead of |'s to separate elements. They could use this method to provide an alternative syntax using |'s.

It might not play well with their tab-expansion system, though.
Link Reply to this
[identity profile] deliberateblank.livejournal.comWed 2004-11-10 15:45
You can fix the non-interactive thingy by using "set -i -o history" in the script, but that presumably needs to be done at the caller's scope and can't be done by the alias/function itself.
Link Reply to this
[identity profile] ewx.livejournal.comWed 2004-11-10 16:12

Cool.

I'm puzzled by the temporary variable - why not:

echo-literally-helper() {
  history 1 | perl -pe 's/^ *[0-9]+ +[^ ]+ //'
}
Link Reply to this | Thread
[personal profile] simontWed 2004-11-10 16:19
Because it's example code, and the real aim is to illustrate that once you've got $str, you can do further string processing on it in any fashion you like. The echo command is really a placeholder for "now do stuff of your choice with".
Link Reply to this | Parent
[identity profile] mobbsy.livejournal.comWed 2004-11-10 16:36
I'm sort of tangentially reminded of an amusing bit of sh I wrote a while ago. It's part of a "seq" work-alike that needed to generate fixed width numbers with arbitrary padding characters (so printf "%.nd" $x wasn't good enough).


### Some stuff to setup $prefix

x=$1

while [[ $x -le $2 ]]
do
echo ${prefix}${x}
ox=$x
x=$(( $x + 1 ))
if [[ $x < $ox ]]
then
prefix=$( echo $prefix | cut -c 2- )
fi
done
Link Reply to this
[identity profile] filecoreinuse.livejournal.comWed 2004-11-10 17:28
Knowing Charlie I'd imagine he thought it was the coolest thing ever and even now is shoing it to his girlfriend on IRC who shal then go boing!!!! and then show me it on IRC :).

I am now fore-warned...
Link Reply to this
[identity profile] senji.livejournal.comFri 2004-11-12 12:02
That's evil.
Link Reply to this
navigation
[ go | Previous Entry | Next Entry ]
[ add | to Memories ]