taT4Nix | Transform HTML to WIKI using GNU sed

Recently, I have joined the forums – http://unix.stackexchange.com/ where I came across the following question;

http://unix.stackexchange.com/questions/11448/how-to-convert-a-href-http-xy-comxy-a-to-http-xy-com-xy

In simple words, this is what was required;

<a href="something">sometext</a>
# transforms into the following wiki markup
[something sometext]

Here’s what I feel should be done using GNU sed;

sed -r 's,<a\s+href=\"([^>]*)\">([^<]*)</a>,[\1 \2],g'

The curve-brackets helps in grouping pattern-matching data, which is then used-by back-references (eg. \1, \2, etc.)
So, in our scenario, we could identify two logical groups;

  1. Data between ‘<a href=”‘ and ‘”>’
  2. Data between ‘”>’ and ‘</a>’

Once groups are identified, using sed back-references, one can format it the way particular wiki markup requires.

Advertisements

Solving GCJ 2009 Qualifying Round’s Question

Feeling bored at office, I thought of surfing the web to look for any upcoming programming contests and I came across Google Code Jam 2010. Registrations are already open and contest is going to begin soon.

So, I looked at the Practice section to do some time pass and came across the question Alien Language. It was good to get back to do something productive and so I did, creating pseudo-code in roughly 30 minutes.

while in.eof
 read line
 split line on spaces into string of 3 blocks..
 L=str[0]
 D=str[1]
 N=str[2]
 break
end

counter=1
while in.eof || counter <= D
 read line
 write line to file #1
end

while in.eof || counter <= N
 read line
 write line to file #2
end

i=1
while f2.eof || i <= N
 case[i-1] = 0
 read line and store into pattern..
 while f1.eof
   read line and store into word..
   if pattern matches word then
     ++case[i-1];
 end
end

Well, the following source code doesn’t look similar to the pseudo-code I wrote above. However, as I no longer code in C/C++/Java and getting used to writing shell-scripts in office irregularly. I thought of doing this with shell-scripting and within 15 minutes, I was ready to test the code.

#!/bin/ksh
# Script Name: gcj09qr_solveq1.ksh
# --- GCJ 2009 QR --- Alien Language

L=
D=
N=

while read line
do
   L=`echo $line | cut -d' ' -f1`
   D=`echo $line | cut -d' ' -f2`
   N=`echo $line | cut -d' ' -f3`
   break
done < $1

#File 1
cat $1 | tail -`expr $(cat $1|wc -l) - 1` | head -$D >  gcjq1_f1.out

Well, as you can see I used a formula to extract the D lines, where each line has 1 word exactly of L characters. I created this formula few weeks back in one of my blog entries.

#File 2
sed 's/(/[/g; s/)/]/g' < $1 | tail -$N >   gcjq1_f2.out

I=1
while read line
do
  echo "Case #$I: $(grep "$line"  gcjq1_f1.out|wc -l)"
  I=`expr $I + 1`
done <  gcjq1_f2.out

This is the way, I thought of solving the case. I tested the code with Small and Large Input case, it worked as expected.

gcj09qr_solveq1.ksh input_file.extn

I guess that could be one of the smallest solution for that question. If I code this in Java, I am sure it will take many more lines to reflect the steps in pseudo-code.

Looking forward to participate in the contest this year. Well, solving this question was a good head start 🙂

taT4Nix | Using visudo To Run Commands With Root Privileges

Recently, I wrote a script to automate the task of mounting the shared folders in Guest OS (Ubuntu 9.10) from Host OS (Windows 7), courtesy of VirtualBox. Now, I couldn’t run that script because I needed root privileges 😐 Although, I have installed the Guest OS, so I know the root password.

However, when VM boots, I am logging in with user account created while installing Guest OS. So, to run certain commands that need root privileges, I have to explicitly use sudo and then enter password, when prompted.

Using visudo

Now, surfing the web led me to a solution, i.e. edit /etc/sudoers file that contains list of privileges given to root and other users. So, to edit this sudoers list, one must run the following;

sudo visudo

You’re prompted for password, enter it and then, you would see something like this;

# /etc/sudoers
## This file MUST be edited with the 'visudo' command as root.
## See the man page for details on how to write a sudoers file.#

Defaults    env_reset

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL) ALL

# Uncomment to allow members of group sudo to not need a password
# (Note that later entries override this, so you might need to move
# it further down)
# %sudo ALL=NOPASSWD: ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

As you can see, the last statement implies that if any user account belongs to admin group, then that user account will have privileges of a super user. So, if I run the following command again, for instance;

sudo visudo

I won’t get any prompt for password and /etc/sudoers without delay.

Trick 2 Gain Root Privileges..

So, go to “System > Administration > Users and Groups” and click on the account properties you want to assign root privileges. Then, switch to “Advanced Tab“, change the “Main Group” to admin. Now, if you have followed till here, it’s time to make following changes to /etc/sudoers file;

# Members of the admin group may gain root privileges
%admin ALL=(ALL)NOPASSWD: ALL   

Now, you have root privileges, you may now run the commands that need root permissions without getting prompt for password. Try doing the same for the script I mentioned in the beginning.

taT4Nix | Mount Shared Folders from Host OS in Guest OS

Brief Overview

I have Ubuntu 9.10 as 64-bit Guest OS running on top of Windows 7 as 64-bit Host OS using VirtualBox 3.1.2. Now, I have also added 3 folders from Windows Filesystem for sharing with Guest OS. As you know, I have to mount the folders by running commands in Terminal for accessing data in shared folders. So, I have to do it manually every time I start the VM.

Latest Updates

Chances are you might not be able to run the following scripts without root privileges, as commands like mount need root privileges. So, refer this blog entry for more details to solve the problem.

Problem Description

I was looking forward to automate this and I came across “System > Preferences > Startup Applications” in my Guest OS. However, I need to run the mount command 3 times for 3 shared folders I have. So, I wrote the following scripts to automate the task and assigning just one script in “Startup Applications”.

Also, I need this because I have created playlists for videos (Movie Player/VLC) and music (Audacious 2), also set desktop background of my choice. These files are only available in shared folders. Now, using single startup script, I would be able to make a copy of music, pictures, videos, etc. every time I login with specific account after starting VM.

Getting Started

To do the needful, I came up with the following script, which would run two more scripts in background, when I login with specific user account. Let’s get started;

share_hostos_data.sh

#!/bin/sh

nohup $HOME/mnt_cp_hostos_data.sh A B C > /dev/null
nohup $HOME/unmnt_hostos_data.sh A B C > /dev/null

Now, that we have startup script ready that will first mount shared folders and then, unmount them. This seems to be stupid if you don’t go below for more details about those two scripts.

Mount Shared Folders and Copy Them Recursively

Now, the following script will accept N arguments where each argument will be the name assigned to shared folder path in Host OS. So, the script will not run with ZERO arguments and it will make the directory under /media/win7-share in Guest OS with the argument name and then, mount the folder before copying the data in the Public directory of specific account’s $HOME.

mnt_cp_hostos_data.sh

#!/bin/sh

if [ $# -eq 0 ]; then
 echo "Exiting.." > /dev/null
 exit 0
fi

for dname in $@
do

 SHARE_DIR=/media/win7-share/$dname

 if [ ! -d ${SHARE_DIR} ]; then
 mkdir ${SHARE_DIR}

 if [ $? -eq 0 ]; then
 echo "${SHARE_DIR} created successfully.."
 else
 exit 1
 fi
 fi

 mount -t vboxsf $dname ${SHARE_DIR}

 if [ $? -eq 0 ]; then
 echo "Mounted $dname successfully.."
 else
 exit 1
 fi

 cp -nr --target-directory=$HOME/Public/windows7/ ${SHARE_DIR}

 if [ $? -eq 0 ]; then
 echo "Copied data into $HOME/Public/windows7/$dname successfully.."
 else
 exit 1
 fi

done

Unmount Shared Folders..

The following script also accepts N arguments where each argument will be the name assigned to shared folder path in Host OS. So, the script will not run with ZERO arguments and it is just going to unmount the directory made the directory under /media/win7-share in Guest OS with the argument name.

unmnt_hostos_data.sh

#!/bin/sh

if [ $# -eq 0 ]; then
 echo "Exiting.." > /dev/null
 exit 0
fi

for dname in $@
do

 SHARE_DIR=/media/win7-share/$dname

 if [ -d ${SHARE_DIR} ]; then
 umount -f ${SHARE_DIR}

 if [ $? -eq 0 ]; then
 echo "Unmounted ${SHARE_DIR} successfully.."
 else
 exit 1
 fi
 fi

done

Work Ahead

As you might have understood by know the shared folders names are A, B, C (see share_hostos_data.sh). That’s something I had to hardcode inside the script for passing them as arguments to mnt_cp* and unmnt* scripts. I ran this command VBoxMange showvminfo “<VM-Name>” in my Host OS command prompt, to find out the names of shared folders.

If I could access the names somehow, then I can pick up these names and supply them as an argument to the necessary scripts created above. That’s all for today, have a great time..