sed and grep tips
It was quite a while since i did any sed, i rediscovered that joy when someone at #sed irc channel asked how to turn "/abc/def/filename" in "<a href="file://A:/abc/def/filename">A:\abc\def\filename</a>".
echo '/abc/def/filename' | sed \ -e 's@.*@A:&@' -e :b\ -e 's@\(>[^/]*[^<]\)/@\1\\@' -e tb
![]()
The first command is really basic, it turns '/abc/def/filename' into '<a href="file://A:/def/filename">A:/abc/def/filename</a>'. The problem here is that the second part remains with slashes instead of backslashes. Conditional branching to help! ':b' means "define label named 'b' here". The substitution means "replace '>' followed by any sequence of not '/', a not '<' and an '/' with captured part (everything but the last '/') and a '\' (double backslash needed to escape it for sed). Basically we are replacing the '/' with '\'. the "tb" part means "jump to label 'b' if the substitution has been performed successfully. :)
But this is terribly inefficient! It performs one initial substitution plus one for each slash and it performs non trivial matching :|.
echo '/abc/def/filename' | sed -e h\ -e 's@/@\\@g' -e G -e \ 's@\([^\n]*\)\n\(.*\)@A:\1@'
This solution kicks of with pushing whatever is in current pattern space (the line that is being currently processed) to hold space. Hold space is as close as you'll get to variables in sed. After that we prepare the backslashed version (replacing all the slashes with backslashes) and than with 'G' we put new line in pattern space and append hold space (the slashed version). We break the pattern space by the new line (remember first part has backslashed version, second slashed) and simply put that in context.
While we are at sed let's look at my submission at the hello world challenge:
set 68 65 6C 6C 6F 1 77 6F 72 6C 64;
while [[ $1 ]]; do
dd if=/dev/urandom bs=1c count=1 2> /dev/null | \
sed -n "/\\x$1/{ p; Q1; }" || shift; done; echo
In a nutshell this looks for "hello world" characters in your /dev/urandom. First thing you'll probably notice are the numbers, they are hex codes of "hello world" ascii values. The code kicks of with set line, it sets the positional parameters to those numbers. With dd we are getting a single character from /dev/urandom and discarding the stats dd gives us. If we find the character we print it and exit with '1'. Since one is considered error code the shift is called, discarding the current first positional parameter (so at the next iteration new character is used). And it keeps looping until it has positional parameter to loop through :). Note that this code is unportable, to the best of my knowledge only gsed has 'Q'.
As a side note, unless you are working with/for ancient bourne shell you should use [[ instead of [.
dpkg -L subversion | egrep "(${PATH//:/.|}.)"

- Image by dannyman via Flickr
Ever wanted to find out what binaries does a certain debian package provide? The above satisfies that curiosity. We get the input from dpkg -L which lists the content of a package. The most interesting bit is happening inside the (), it uses parameter expansion feature of shell to replace the : (the standard PATH delimiter) with a '|'. The '.' are only there to make sure something is following the path, so that empty directories don't get matched.
Ever had a huge config file with shitload of examples? But you only wanted to find out what is currently being used?
alias nco="egrep -v '^[[:space:]]*(#|$)'"
This little alias excludes all the empty lines and the comments (assuming comments start with '#'). Use it like:
nco filename something | nco
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=fac74fac-94e9-44a2-8626-7217b55fb065)