<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8501563347891351832</id><updated>2024-09-16T00:24:24.374+02:00</updated><category term="linux"/><category term="awk"/><category term="terminal"/><category term="command line"/><category term="tee"/><category term="bash"/><category term="calendar"/><category term="cpulimit"/><category term="diff"/><category term="google"/><category term="parsing"/><category term="process substitution"/><category term="programming"/><category term="sed"/><category term="shell"/><category term="task scheduling"/><category term="wget"/><category term="xargs"/><title type='text'>Programming, hacking, Linux and beyond</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8501563347891351832.post-4642498932039669790</id><published>2012-04-26T23:49:00.004+02:00</published><updated>2012-04-27T00:30:09.328+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="awk"/><category scheme="http://www.blogger.com/atom/ns#" term="bash"/><category scheme="http://www.blogger.com/atom/ns#" term="calendar"/><category scheme="http://www.blogger.com/atom/ns#" term="google"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="task scheduling"/><category scheme="http://www.blogger.com/atom/ns#" term="terminal"/><title type='text'>Google command line tools: Google calendar task scheduler</title><content type='html'>The other day I stumbled upon something called&amp;nbsp;&lt;a href=&quot;http://code.google.com/p/googlecl/&quot; target=&quot;_blank&quot;&gt;googlecl&lt;/a&gt;&amp;nbsp;which packs different clients for different google services. I couldn&#39;t wait to test it out so in combination with an idea from the work of&amp;nbsp;&lt;a href=&quot;http://ferntreeshack.blogspot.se/2012/04/google-calendar-automation-part-1.html&quot; target=&quot;_blank&quot;&gt;this guy&lt;/a&gt;, I decided to write a task scheduler entierly controlled by google calendar.&lt;br /&gt;
&lt;br /&gt;
Since I need training in bash scripting, plus it is kind of a simple thing to do - I decided to write it as a bash script.&lt;br /&gt;
&lt;br /&gt;
It is dead simple to schedule a task. It can be run once or periodically.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWArp0iQb9G0Q9rbtJOoczWQcXQQAGWybXn6WvIModhsVmF1hfCbw30tKI1IdrcelQDmOaUFLD3en4Awa78adKUfMjwj44gmtMBcs_TruxhcO343H-M2hQkV5jilwGykyZSjogyDOCWWIs/s1600/Screenshot+at+2012-04-26+23:11:10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;280&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWArp0iQb9G0Q9rbtJOoczWQcXQQAGWybXn6WvIModhsVmF1hfCbw30tKI1IdrcelQDmOaUFLD3en4Awa78adKUfMjwj44gmtMBcs_TruxhcO343H-M2hQkV5jilwGykyZSjogyDOCWWIs/s640/Screenshot+at+2012-04-26+23:11:10.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Sorry for the image being in swedish, the language settings did affect gmail but not google calendar. Anyway, the procedure is as follows.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Install the googlecl tools. Use it with your calendar so that you are forced to complete the verification procedure. (i.e &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ google calendar today&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Fire up google calendar and create a new task.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Enter a title for the task. The title must begin with gcmd for the scheduler daemon to pick it up.&lt;/li&gt;
&lt;li&gt;Enter the start and finish times (currently the time range cannot span over several days).&lt;/li&gt;
&lt;li&gt;In the &quot;where&quot; field, start with the flag &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;-i &lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;followed by the interval with which to run the task (in seconds, 0 to only run it once).&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Continue by adding &lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&amp;nbsp;which means &quot;end of arguments&quot;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Finish up by entering your command of choice last. Note that the initial run is scheduled using &lt;i&gt;at, &lt;/i&gt;which does not have any PATH variable set. In other words, give full path names.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Run the &lt;i&gt;gcmd&amp;nbsp;&lt;/i&gt;script.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
It is probably best to schedule the gcmd script to run every minute or so using crontab to have it catch the updates when you&#39;re adding tasks at work, the bus, the car, the empire state building, you get the point.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Let&#39;s look at the script. It&#39;s quite commented so I don&#39;t feel a need to explain anything further.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;gcmd&lt;/code&gt;&lt;br /&gt;
&lt;pre style=&quot;background-attachment: initial; background-clip: initial; background-color: #f0f0f0; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-color: rgb(204, 204, 204); border-bottom-style: dashed; border-bottom-width: 1px; border-image: initial; border-left-color: rgb(204, 204, 204); border-left-style: dashed; border-left-width: 1px; border-right-color: rgb(204, 204, 204); border-right-style: dashed; border-right-width: 1px; border-top-color: rgb(204, 204, 204); border-top-style: dashed; border-top-width: 1px; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow-x: auto; overflow-y: auto; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;#!/usr/bin/env bash

&lt;span style=&quot;color: blue;&quot;&gt;# 1. Get todays tasks from google, grab only those starting with gcmd.
#    Loop over the different tasks.&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
google calendar today --fields &quot;title,where,when,id&quot; \
  | awk -F, &#39;/gcmd/&#39; \
  | while read line; do

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 2. Default args. These are overridden by args read from the
  #    where field of the task.&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;

  # Interval between executions, 0 to only run once.
  interval=0

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 3. Get arguments from the where field and overwrite default values.&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
  set -- $(getopt i: &quot;$(echo &quot;$line&quot; | awk -F, &#39;{print $2}&#39;)&quot;)
  while [ $# -gt 0 ]; do
    case &quot;$1&quot; in
      (-i) interval=$2; shift;;
      (--) shift; break;; # Terminates the args
      (-*) echo &quot;$0 error - unrecognized arg $1&quot; 1&amp;gt;&amp;amp;2; exit 1;;
      (*) break;;
    esac
    shift
  done

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 4. Get the unique ID and construct a filename of it. The id is displayed
  #    as a URL, ending with a unique id.&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
  arr=($(echo &quot;$line&quot;|awk -F, &#39;{print $4}&#39;|tr &quot;/&quot; &quot; &quot;))
  filename=&quot;/tmp/.gcmd_${arr[${#arr[@]} - 1]}&quot;
  command=&quot;$*&quot;

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 5. If the job has already been scheduled, un-schedule the job and
  #    remove the file&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
  if [ -e &quot;$filename&quot; ]; then
    echo &quot;File exists, re-scheduling&quot;
    atrm $(cat &quot;$filename&quot;)
  else
    echo &quot;New job \&quot;$(echo ${line}|awk -F, &#39;{print $1}&#39;)\&quot;&quot;
  fi

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 6. Get the desired time to run/stop. This should be improved to account for
  #    date aswell. Currently we only parse the time, which isn&#39;t enough if we need
  #    to run the task for several days.&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
  time=&quot;$(echo ${line}|awk -F, &#39;{print $3}&#39;|awk -F- &#39;{print $1}&#39;|awk &#39;{print $3}&#39;)&quot;
  stoptime=&quot;$(echo ${line}|awk -F, &#39;{print $3}&#39;|awk -F- &#39;{print $2}&#39;|awk &#39;{print $3}&#39;)&quot;

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;
  # 7. If an interval is specified, make the command run according to the interval specified.
  #    This can be improved since it doesn&#39;t take into account how long the job takes to run so
  #    the interval will be more like interval + time to run task.
&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;  if [ $interval -ne 0 ]; then
    command=&quot;stoptime=$(date -d ${stoptime} +%s); gcmdfun() { ${command}; }; while [ \$(date +%s) -lt \$stoptime ]; do gcmdfun; sleep $interval; done;&quot;
  fi

&lt;/code&gt;&lt;code style=&quot;word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;  # 8. Schedule the command to run using at and store the job number in a file (named by the unique id).
&lt;/span&gt;&lt;/code&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;  echo &quot;$command&quot; | at &quot;$time&quot; 2&amp;gt;&amp;amp;1 | awk &#39;/job/{print $2}&#39; &amp;gt; &quot;$filename&quot;
done&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
It&#39;s late over here now. Enjoy and Good night!&lt;br /&gt;
&lt;ol&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/4642498932039669790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/google-command-line-tools-google.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/4642498932039669790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/4642498932039669790'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/google-command-line-tools-google.html' title='Google command line tools: Google calendar task scheduler'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWArp0iQb9G0Q9rbtJOoczWQcXQQAGWybXn6WvIModhsVmF1hfCbw30tKI1IdrcelQDmOaUFLD3en4Awa78adKUfMjwj44gmtMBcs_TruxhcO343H-M2hQkV5jilwGykyZSjogyDOCWWIs/s72-c/Screenshot+at+2012-04-26+23:11:10.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501563347891351832.post-1168240033650791113</id><published>2012-04-24T20:08:00.000+02:00</published><updated>2012-04-24T20:08:33.659+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="command line"/><category scheme="http://www.blogger.com/atom/ns#" term="cpulimit"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="terminal"/><title type='text'>Cpulimit: take control over your CPU</title><content type='html'>Cpulimit is a tool that is very handy to have when doing data processing and other time consuming tasks. What it does is that it limits the CPU utilization of a process/program to a certain amount.&lt;br /&gt;
&lt;br /&gt;
Imagine you started a cpu-hogging process and needs resources for other things&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ cpulimit --limit=50 --pid=1234&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;That will attach to the process and limit it&#39;s usage of cpu cycles to 50 percent of the available.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Cool!&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/1168240033650791113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/cpulimit-take-control-over-your-cpu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/1168240033650791113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/1168240033650791113'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/cpulimit-take-control-over-your-cpu.html' title='Cpulimit: take control over your CPU'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501563347891351832.post-9156599750153206737</id><published>2012-04-24T19:48:00.002+02:00</published><updated>2012-04-24T19:48:45.614+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="diff"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="process substitution"/><category scheme="http://www.blogger.com/atom/ns#" term="tee"/><title type='text'>Process substitution</title><content type='html'>&lt;br /&gt;
&lt;h2&gt;
Process substitution&lt;/h2&gt;
Process substitution takes the form&amp;nbsp;of &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;lt;(list)&lt;/span&gt; or &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;gt;(list)&lt;/span&gt;. The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file&amp;nbsp;is passed as an argument to the current command as the result of the&amp;nbsp;expansion. If the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;gt;(list)&lt;/span&gt; form is used, writing to the file will provide input for list. If the &lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;lt;(list)&lt;/span&gt; form is used, the file passed as&amp;nbsp;an argument should be read to obtain the output of list.&amp;nbsp;When available, process substitution is performed simultaneously with&amp;nbsp;parameter and variable expansion, command substitution, and arithmetic expansion.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So what does this mean? Well basically that you can substitute files for command input/output. Imagine you want to compare the output of two files using diff you could do something like&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ diff &amp;lt;(echo afile) &amp;lt;(echo anotherfile)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
Now, the real power comes with using process substitution in conjunction with tee. Just look at the next command and be stunned with the usefulness of this little nifty piece of feature.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;ps aux | tee &amp;gt;(grep ^root &amp;gt; /tmp/rootps) &amp;gt;(grep ^simon &amp;gt; /tmp/simon)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Which will list all processes, write all processes owned by root to one file and the processes owned by simon to another file.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
Convenient, huh?&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/9156599750153206737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/process-substitution.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/9156599750153206737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/9156599750153206737'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/process-substitution.html' title='Process substitution'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501563347891351832.post-2755226098867376854</id><published>2012-04-24T19:20:00.002+02:00</published><updated>2012-04-24T19:56:17.828+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="awk"/><category scheme="http://www.blogger.com/atom/ns#" term="command line"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="sed"/><category scheme="http://www.blogger.com/atom/ns#" term="tee"/><category scheme="http://www.blogger.com/atom/ns#" term="terminal"/><category scheme="http://www.blogger.com/atom/ns#" term="wget"/><category scheme="http://www.blogger.com/atom/ns#" term="xargs"/><title type='text'>5 Linux shell commands you should know about</title><content type='html'>&lt;br /&gt;
&lt;h2&gt;


5 Linux shell commands you should know about&lt;/h2&gt;
Over the years I have gotten used to some very nifty commandline tools that I use more or less every day. Let&#39;s go through five of them right here.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;This article will assume you have basic knowledge of the bash shell (good tutorial here&amp;nbsp;&lt;a href=&quot;http://mywiki.wooledge.org/BashGuide&quot;&gt;http://mywiki.wooledge.org/BashGuide&lt;/a&gt;).&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;
&lt;h3&gt;


#1 tee&lt;/h3&gt;
&lt;div&gt;
The `tee&#39; command copies standard input to standard output and also to&amp;nbsp;any files given as arguments. &amp;nbsp;This is useful when you want not only to&amp;nbsp;send some data down a pipe, but also to save a copy.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ ./longrunningprocess | tee data.log&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;That is probably the simplest way you can use tee. Since it passes the stream on to stdout again you can use it as a proxy - storing the data to file but passing it on to the next command.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;cat data | awk &#39;{print $1+1}&#39; | tee plusone | awk &#39;{print $1-2}&#39; &amp;gt; minusone&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
What that line does is - take the file&amp;nbsp;&lt;i&gt;data&lt;/i&gt;, containing some rows with numbers in it, pass it to awk and add one to each line, pass the modified stream to tee which stores it to file and once again passes it on to awk which subtracts two and writes it to another file.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Another more interesting way to do the same thing is&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$ cat data | tee &amp;gt;(awk &#39;{print $1+1}&#39; &amp;gt; plusone) &amp;gt;(awk &#39;{print $1-1}&#39; &amp;gt; minusone)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
which sends the output of data to two pipes running their separate versions of the awk script.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;


#2 wget&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
Wget is one of those tools that I use the most. Combining it with tee can make it a powerful tool.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;wget www.kernel.org/pub/linux/kernel/v3.0/testing/linux-3.4-rc4.tar.bz2 -O - | tee kernel.tar.bz2 | tar xjvf -&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
That will download the linux kernel, have tee store it to file while tar decompresses it on the fly.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;


#3 awk&lt;/h3&gt;
&lt;div&gt;
GNU awk is totally invaluable to me. I won&#39;t go in-depth on it here but look at my earlier post covering awk&amp;nbsp;&lt;a href=&quot;http://simonslinuxworld.blogspot.se/2012/04/awk-tutorial-by-example.html&quot;&gt;http://simonslinuxworld.blogspot.se/2012/04/awk-tutorial-by-example.html&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;


#4 sed&lt;/h3&gt;
&lt;div&gt;
Sed is a stream editor - that is - pass a stream to it, tell it what to edit and how to do it - store the output, or do something equally useful with it.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Let&#39;s say I know a guy, who knows a guy who once downloaded a season of a TV-show illegally. He told me how he needed to rename the files of the show to a specific naming convention for his XBMC media center to be able to download information about the show from some website. In this case (and many others) sed is needed.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;ls | sed -r &quot;s/(.+)_(.+).mkv/mv &amp;amp; \&quot;Series (2012) \2.mkv\&quot;/&quot; | bash&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Piece of cake - list files, substitute the filename&amp;nbsp;&lt;i&gt;series_S01EXX.mkv&amp;nbsp;&lt;/i&gt;&amp;nbsp;for&amp;nbsp;&lt;i&gt;mv series_S01EXX.mkv &quot;Series (2012) S01EXX.mkv&quot;&lt;/i&gt;, pass it to bash for evaluation.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
If you want bittorrent to still find the original files just make symlinks instead of moving the file (that&#39;s what&amp;nbsp;&lt;i&gt;he&lt;/i&gt;&amp;nbsp;did).&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;


#5 xargs&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;
xargs reads items&amp;nbsp;from stdin, delimited by blanks&amp;nbsp;or newlines, and executes&amp;nbsp;the &amp;nbsp;command one or more times with any initial arguments followed by items read from standard input. Blank lines on&amp;nbsp;the standard input are ignored.&lt;br /&gt;
&lt;br /&gt;
Example: Remove all files matching pattern *~ (tempoary emacs files) recursively.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;find . -name &quot;*~&quot; -type f -print | xargs rm -f&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
If you need more control over how the items are inserted into the command to execute you can use {}, which gets substituted by the actual item when the command is executed. E.g.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;$&amp;nbsp;find . -name &quot;*~&quot; -type f -print | xargs -n 1 -I{} mv {} /tmp&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;Since mv only accepts two paths we add -n 1 to xargs to make it execute each command with one of the arguments. -I{} is used to tell xargs to use {} for substitution.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;h3&gt;


&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Final words&lt;/span&gt;&lt;/h3&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;I hope you have enjoyed this little infomative post about useful linux commands.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;There&#39;s a lot of options to them so I suggest you check out the manpages to make full use of the commands.&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/2755226098867376854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/5-linux-shell-commands-you-should-know.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/2755226098867376854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/2755226098867376854'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/5-linux-shell-commands-you-should-know.html' title='5 Linux shell commands you should know about'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8501563347891351832.post-2212694436535190336</id><published>2012-04-13T01:18:00.003+02:00</published><updated>2012-04-13T12:59:28.077+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="awk"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="parsing"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="shell"/><title type='text'>AWK Tutorial By Example</title><content type='html'>Awk is a really nifty tool for filtering large chunks of text as well as for gathering statistics or substituting words within the text.&lt;br /&gt;
&lt;br /&gt;
Unlike many other IT tutorials I will be keeping this tutorial short and concise and get to the most basic and interesting stuff right away by a short example.&lt;br /&gt;
&lt;br /&gt;
Imagine you have a CSV file containing statistical data of a group of people containing their IQ and their age, like so (file could actually be thousands of lines long):&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;data.csv&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
123,34  
119,23  
100,56
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
Now what I like to do is to find the mean age, mean IQ and standard deviation for them both and output them in structured way. Seems like lots of lots of code? Not with awk!&lt;br /&gt;
&lt;br /&gt;
We start off by making a simple script that calculates the mean values for both columns, look at the code below.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;script.awk&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
BEGIN {
    sum_iq=0;
    sum_age=0; 
}
{
    sum_iq = sum_iq + $1;
    sum_age = sum_age + $2;
}
END {
    print &quot;Mean IQ: &quot; sum_iq/NR;
    print &quot;Mean age: &quot; sum_age/NR;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Execute the following to test the script:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
$ cat data.csv | awk -F, -f script.awk
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
This pipes the contents of &lt;i&gt;data.csv&lt;/i&gt;&amp;nbsp;to awk, which is run with the field terminator , (comma) and script file &lt;i&gt;script.awk&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
To explain what is happening in the script you have to know that awk is designed to be executed on batches of lines of text (i.e. text files). For each line in the file, the script is executed - retaining its variables values. Awk scripts are organized in the form.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
&lt;i&gt;pattern&lt;/i&gt;{&lt;b&gt;action&lt;/b&gt;}
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
When a pattern is matched, the action (stuff between the curly braces) are executed. A pattern can be a keyword like &lt;i&gt;BEGIN&lt;/i&gt; or &lt;i&gt;END&lt;/i&gt; as we use here, completely empty (matching every line) or a regular expression contained between two forward slashes.&lt;br /&gt;
&lt;br /&gt;
So what happens in our script is the following:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;The first line is fed to the script, since this is the first line the pattern &lt;i&gt;BEGIN&lt;/i&gt; is matched. Within the block we set the variables &lt;i&gt;sum_age&lt;/i&gt;&amp;nbsp;and &lt;i&gt;sum_iq&lt;/i&gt;&amp;nbsp;to &lt;i&gt;0&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;Still on the first line but now the second curly-brace-block is matched (remember, it matches every line). Inside the block we add the value from the first column to the &lt;i&gt;sum_iq&lt;/i&gt;&amp;nbsp;variable and the value from the second column to the &lt;i&gt;sum_age&lt;/i&gt;&amp;nbsp;variable.&lt;/li&gt;
&lt;li&gt;The rest of the lines are matched and added to the sum variables.&lt;/li&gt;
&lt;li&gt;On the last line the &lt;i&gt;END&lt;/i&gt;&amp;nbsp;pattern is matched. Here we simply print out the sums divided by the keyword &lt;i&gt;NR&lt;/i&gt;&amp;nbsp;which is awk&#39;s line counter. Anywhere in the script it can be used as a variable, telling us on which line we are, special case is the last line - in this case NR tells us how many lines the file has.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Just to show off we can add a standard deviation calculation like this.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre style=&quot;background-image: URL(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNtyR0g-PwqeHdBdpCxOy2emQ7vV4rhlYIRqe58uO2WYrb_wmaeyDLjIPGwOGICKnHxDKjVcpxGxvg-MZ-p9xMgNNaalhHKFeKsF3fENvZMvNW3Feh1pD0NnNo1COiUL1_7NrUVEYmlX0J/s320/codebg.gif); background: #f0f0f0; border: 1px dashed #CCCCCC; color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt;
BEGIN {
    sum_iq=0;
    sum_age=0; 
}
{
    sum_iq = sum_iq + $1;
    sum_age = sum_age + $2;
    iq[NR] = $1;
    age[NR] = $2;
}
END {
    mean_iq = sum_iq/NR;
    mean_age = sum_age/NR;
    stdd_iq = 0;
    stdd_age = 0;
    for(i=1; i&amp;lt;=NR; i++) {
        stdd_iq += (iq[i] - mean_iq)**2;
        stdd_age += (age[i] - mean_age)**2;
    }
    stdd_iq = sqrt(stdd_iq/(NR-1));
    stdd_age = sqrt(stdd_age/(NR-1));
    print &quot;Mean IQ: &quot; mean_iq &quot; (&quot; stdd_iq &quot;)&quot;;
    print &quot;Mean age: &quot; mean_age &quot; (&quot; stdd_age &quot;)&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
A simple estimation of standard deviation on an observed set is&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw6RE238IMh0FGjKMXpAN1xZe-OfABiboUzzXygytkpoN0SAc58HEGAGKY9guZycUgAxuMA82RFpQE9Diwj0tOiF_SANbYwLLYqVfGspKFLG6ymhz3nOnXofM-mma43C-5PlAC-iq3Ml5X/s1600/Screenshot+at+2012-04-13+01:05:42.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw6RE238IMh0FGjKMXpAN1xZe-OfABiboUzzXygytkpoN0SAc58HEGAGKY9guZycUgAxuMA82RFpQE9Diwj0tOiF_SANbYwLLYqVfGspKFLG6ymhz3nOnXofM-mma43C-5PlAC-iq3Ml5X/s1600/Screenshot+at+2012-04-13+01:05:42.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
this means that we need to use arrays to store all values for all rows. Then take each value, subtract the mean value (expected value), square it, sum all together and divide by number of rows (the &lt;i&gt;NR&lt;/i&gt;) keyword minus one and finally take the square root of the calculations as the result.&lt;br /&gt;
&lt;br /&gt;
You should not that there is no checking for blank or invalid lines in this code, that&#39;s an exercise for the reader.&lt;br /&gt;
&lt;br /&gt;
Make sure to check out this awesome and much more in-depth tutorial on awk:&amp;nbsp;&lt;a href=&quot;http://www.grymoire.com/Unix/Awk.html&quot;&gt;http://www.grymoire.com/Unix/Awk.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
For some really cool examples and ideas, this blog is number one:&lt;br /&gt;
&lt;a href=&quot;http://www.thegeekstuff.com/tag/awk-tutorial-examples/&quot;&gt;http://www.thegeekstuff.com/tag/awk-tutorial-examples/&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;
I hoped you enjoyed this little tutorial and post some links to my brand new blog all over the internet ;)</content><link rel='replies' type='application/atom+xml' href='http://simonslinuxworld.blogspot.com/feeds/2212694436535190336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/awk-tutorial-by-example.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/2212694436535190336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8501563347891351832/posts/default/2212694436535190336'/><link rel='alternate' type='text/html' href='http://simonslinuxworld.blogspot.com/2012/04/awk-tutorial-by-example.html' title='AWK Tutorial By Example'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/00683876004563348402</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw6RE238IMh0FGjKMXpAN1xZe-OfABiboUzzXygytkpoN0SAc58HEGAGKY9guZycUgAxuMA82RFpQE9Diwj0tOiF_SANbYwLLYqVfGspKFLG6ymhz3nOnXofM-mma43C-5PlAC-iq3Ml5X/s72-c/Screenshot+at+2012-04-13+01:05:42.png" height="72" width="72"/><thr:total>0</thr:total></entry></feed>