{"id":3453,"date":"2014-08-21T00:35:11","date_gmt":"2014-08-20T16:35:11","guid":{"rendered":"http:\/\/rmohan.com\/?p=3453"},"modified":"2014-08-21T00:36:11","modified_gmt":"2014-08-20T16:36:11","slug":"ksh-scripting","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=3453","title":{"rendered":"Ksh Scripting"},"content":{"rendered":"<p>Principle of Script<\/p>\n<p>Defining the Shell Type<\/p>\n<p>To make a ksh script (which is a ksh program) crate a new file with a starting line like:<br \/>\n#!\/usr\/bin\/ksh<br \/>\nIt is important that the path to the ksh is propper and that the line doesn not have more than 32 characters. The shell from which you are starting the script will find this line and and hand the whole script over to to ksh. Without this line the script would be interpreted by the same typ of shell as the one, from which it was started. But since the syntax is different for all shells, it is necessary to define the shell with that line.<\/p>\n<p>Four Types of Lines<\/p>\n<p>A script has four types of lines: The shell defining line at the top, empty lines, commentary lines starting with a # and command lines. See the following top of a script as an example for these types of lines:<\/p>\n<p>#!\/usr\/bin\/ksh<\/p>\n<p># Commentary&#8230;&#8230;<\/p>\n<p>file=\/path\/file<br \/>\nif [[ $file = $1 ]];then<br \/>\n   command<br \/>\nfi<br \/>\nStart and End of Script<\/p>\n<p>The script starts at the first line and ends either when it encounters an &#8220;exit&#8221; or the last line. All &#8220;#&#8221; lines are ignored.<\/p>\n<p>Start and End of Command<\/p>\n<p>A command starts with the first word on a line or if it&#8217;s the second command on a line with the first word after a&#8221;;&#8217;.<br \/>\nA command ends either at the end of the line or whith a &#8220;;&#8221;. So one can put several commands onto one line:<\/p>\n<p>print -n &#8220;Name: &#8220;; read name; print &#8220;&#8221;<\/p>\n<p>One can continue commands over more than one line with a &#8220;\\&#8221; immediately followed by a newline sign which is made be the return key:<\/p>\n<p>grep filename | sort -u | awk &#8216;{print $4}&#8217; | \\<br \/>\nuniq -c >> \/longpath\/file<br \/>\nName and Permissions of Script File<\/p>\n<p>The script mus not have a name which is identical to a unix command: So the script must NOT be called &#8220;test&#8221;!<br \/>\nAfter saveing the file give it the execute permissions with: chmod 700 filename.<\/p>\n<p>Variables<\/p>\n<p>Filling in<\/p>\n<p>When filling into a variable then one uses just it&#8217;s name: state=&#8221;US&#8221; and no blanks. There is no difference between strings and numbers: price=50.<\/p>\n<p>Using<\/p>\n<p>When using a variable one needs to put a $ sign in front of it: print $state $price.<\/p>\n<p>Arrays<\/p>\n<p>Set and use an array like:<\/p>\n<p>arrname[1]=4\tTo fill in<br \/>\nprint ${arraname[1]}\tTo print out<br \/>\n${arrname[*]}\tGet all elements<br \/>\n${#arrname[*]}\tGet the number of elements<br \/>\nDeclaration<\/p>\n<p>There are happily no declarations of variables needed in ksh. One cannot have decimals only integers.<\/p>\n<p>Branching<\/p>\n<p>if then fi<\/p>\n<p>if [[ $value -eq 7 ]];then<br \/>\n   print &#8220;$value is 7&#8221;<br \/>\nfi<br \/>\nor:<\/p>\n<p>if [[ $value -eq 7 ]]<br \/>\nthen<br \/>\n   print &#8220;$value is 7&#8221;<br \/>\nfi<br \/>\nor:<\/p>\n<p>if [[ $value -eq 7 ]];then print &#8220;$value is 7&#8221;;fi<br \/>\nif then else fi<\/p>\n<p>if [[ $name = &#8220;John&#8221; ]];then<br \/>\n   print &#8220;Your welcome, ${name}.&#8221;<br \/>\nelse<br \/>\n   print &#8220;Good bye, ${name}!&#8221;<br \/>\nfi<br \/>\nif then elif then else fi<\/p>\n<p>if [[ $name = &#8220;John&#8221; ]];then<br \/>\n   print &#8220;Your welcome, ${name}.&#8221;<br \/>\nelif [[ $name = &#8220;Hanna&#8221; ]];then<br \/>\n   print &#8220;Hello, ${name}, who are you?&#8221;<br \/>\nelse<br \/>\n   print &#8220;Good bye, ${name}!&#8221;<br \/>\nfi<br \/>\ncase esac<\/p>\n<p>case $var in<br \/>\n   john|fred) print $invitation;;<br \/>\n   martin)    print $declination;;<br \/>\n   *)         print &#8220;Wrong name&#8230;&#8221;;;<br \/>\nesac<br \/>\nLooping<\/p>\n<p>while do done<\/p>\n<p>while [[ $count -gt 0 ]];do<br \/>\n   print &#8220;\\$count is $count&#8221;<br \/>\n   (( count -= 1 ))<br \/>\ndone<br \/>\nuntil do done<\/p>\n<p>until [[ $answer = &#8220;yes&#8221; ]];do<br \/>\n   print -n &#8220;Please enter \\&#8221;yes\\&#8221;: &#8221;<br \/>\n   read answer<br \/>\n   print &#8220;&#8221;<br \/>\ndone<br \/>\nfor var in list do done<\/p>\n<p>for foo in $(ls);do<br \/>\n   if [[ -d $foo ]];then<br \/>\n      print &#8220;$foo is a directory&#8221;<br \/>\n   else<br \/>\n      print &#8220;$foo is not a directory&#8221;<br \/>\n   fi<br \/>\ndone<br \/>\ncontinue&#8230;break<\/p>\n<p>One can skip the rest of a loop and directly go to the next iteration with: &#8220;continue&#8221;.<\/p>\n<p>while read line<br \/>\ndo<br \/>\n   if [[ $line = *.gz ]];then<br \/>\n      continue<br \/>\n   else<br \/>\n      print $line<br \/>\n   fi<br \/>\ndone<br \/>\nOne can also prematurely leave a loop with: &#8220;break&#8221;.<\/p>\n<p>while read line;do<br \/>\n   if [[ $line = *!(.c) ]];then<br \/>\n      break<br \/>\n   else<br \/>\n      print $line<br \/>\n   fi<br \/>\ndone<br \/>\nCommand Line Arguments<\/p>\n<p>(Officially they are called &#8220;positional parameters&#8221;)<\/p>\n<p>The number of command line arguments is stored in $# so one can check<br \/>\nfor arguments with:<br \/>\nif [[ $# -eq 0 ]];then<br \/>\n   print &#8220;No Arguments&#8221;<br \/>\n   exit<br \/>\nfi<br \/>\nThe single Arguments are stored in $1, &#8230;.$n and all are in $* as one string. The arguments cannot<br \/>\ndirectly be modified but one can reset the hole commandline for another part of the program.<br \/>\nIf we need a first argument $first for the rest of the program we do:<br \/>\nif [[ $1 != $first ]];then<br \/>\n   set $first $*<br \/>\nfi<br \/>\nOne can iterate over the command line arguments with the help of the shift command. Shift indirectly removes the first argument.<br \/>\nuntil [[ $# -qe 0 ]];do<br \/>\n   # commands &#8230;.<br \/>\n   shift<br \/>\ndone<br \/>\nOne can also iterate with the for loop, the default with for is $*:<\/p>\n<p>for arg;do<br \/>\n   print $arg<br \/>\ndone<br \/>\nThe program name is stored in $0 but it contains the path also!<\/p>\n<p>Comparisons<\/p>\n<p>To compare strings one uses &#8220;=&#8221; for equal and &#8220;!=&#8221; for not equal.<br \/>\nTo compare numbers one uses &#8220;-eq&#8221; for equal &#8220;-ne&#8221; for not equal as well as &#8220;-gt&#8221; for greater than<br \/>\nand &#8220;-lt&#8221; for less than.<\/p>\n<p>if [[ $name = &#8220;John&#8221; ]];then<br \/>\n   # commands&#8230;.<br \/>\nfi<br \/>\nif [[ $size -eq 1000 ]];then<br \/>\n   # commands&#8230;.<br \/>\nfi<br \/>\nWith &#8220;&#038;&#038;&#8221; for &#8220;AND&#8221; and &#8220;||&#8221; for &#8220;OR&#8221; one can combine statements:<\/p>\n<p>if [[ $price -lt 1000 || $name = &#8220;Hanna&#8221; ]];then<br \/>\n   # commands&#8230;.<br \/>\nfi<br \/>\nif [[ $name = &#8220;Fred&#8221; &#038;&#038; $city = &#8220;Denver&#8221; ]];then<br \/>\n   # commands&#8230;.<br \/>\nfi<\/p>\n<p>Variable Manipulations<\/p>\n<p>Removing something from a variable<\/p>\n<p>Variables that contain a path can very easily be stripped of it: ${name##*\/} gives you just the filename.<br \/>\nOr if one wants the path: ${name%\/*}. % takes it away from the left and # from the right.<br \/>\n%% and ## take the longest possibility while % and # just take the shortest one.<br \/>\nReplacing a variable if it does not yet exits<\/p>\n<p>If we wanted $foo or if not set 4 then: ${foo:-4} but it still remains unset. To change that we use:<br \/>\n${foo:=4}<br \/>\nExiting and stating something if variable is not set<\/p>\n<p>This is very important if our program relays on a certain vaiable: ${foo:?&#8221;foo not set!&#8221;}<br \/>\nJust check for the variable<\/p>\n<p>${foo:+1} gives one if $foo is set, otherwise nothing.<\/p>\n<p>Ksh Regular Expressions<\/p>\n<p>Ksh has it&#8217;s own regular expressions.<br \/>\nUse an * for any string. So to get all the files ending it .c use *.c.<br \/>\nA single character is represented with a ?. So all the files starting with any sign followed bye 44.f can be fetched by: ?44.f.<\/p>\n<p>Especially in ksh there are quantifiers for whole patterns:<\/p>\n<p>?(pattern) matches zero or one times the pattern.<br \/>\n*(pattern) matches any time the pattern.<br \/>\n+(pattern) matches one or more time the pattern.<br \/>\n@(pattern) matches one time the pattern.<br \/>\n!(pattern) matches string without the pattern.<\/p>\n<p>So one can question a string in a variable like: if [[ $var = fo@(?4*67).c ]];then &#8230;<\/p>\n<p>Functions<\/p>\n<p>Description<\/p>\n<p>A function (= procedure) must be defined before it is called, because ksh is interpreted at run time.<br \/>\nIt knows all the variables from the calling shell except the commandline arguments. But has it&#8217;s<br \/>\nown command line arguments so that one can call it with different values from different places in<br \/>\nthe script. It has an exit status but cannot return a value like a c funcition can.<br \/>\nMaking a Function<\/p>\n<p>One can make one in either of the following two ways:<br \/>\nfunction foo {<br \/>\n   # commands&#8230;<br \/>\n}<\/p>\n<p>foo(){<br \/>\n   # commands&#8230;<br \/>\n}<br \/>\nCalling the Function<\/p>\n<p>To call it just put it&#8217;s name in the script: foo. To give it arguments do: foo arg1 arg2 &#8230;<br \/>\nThe arguments are there in the form of $1&#8230;$n and $* for all at once like in the main code.<br \/>\nAnd the main $1 is not influenced bye the $1 of a particular function.<br \/>\nReturn<\/p>\n<p>The return statement exits the function imediately with the specified return value as an exit status.<\/p>\n<p>Data Redirection<\/p>\n<p>General<\/p>\n<p>Data redirection is done with the follwoing signs: &#8220;> >> < <<\". Every program has at least a\n\nstandardinput, standardoutput and standarderroroutput. All of these can be redirected.\n\nCommand Output to File\n\nFor writing into a new file or for overwriting a file do: command > file<\/p>\n<p>For appending to a file do: command >> file<\/p>\n<p>Standard Error Redirection<\/p>\n<p>To redirect the error output of a command do: command 2> file<\/p>\n<p>To discard the error alltogether do: command 2>\/dev\/null<\/p>\n<p>To put the error to the same location as the normal output do: command 2>&#038;1<\/p>\n<p>File into Command<\/p>\n<p>If a program needs a file for input over standard input do: command < file\n\nCombine Input and Output Redirection\n\ncommand < infile > outfile<br \/>\ncommand < infile > outfile 2>\/dev\/null<\/p>\n<p>Commands into Program ( Here Document )<\/p>\n<p>Every unix command can take it&#8217;s commands from a text like listing with:<\/p>\n<p>command <<EOF\ninput1\ninput2\ninput3\nEOF\n\nFrom eof to eof all is feeded into the above mentioned command.\n\n\nPipes\n\nFor a serial processing of data from one command to the next do:\ncommand1 | command2 | command3 ...\ne.g. last | awk '{print $1}' | sort -u.\n\n\nCoprocesses\n\nOne can have one background process with which one can comunicate with read -p and print -p. It is started with command |&#038;. If one uses: ksh |&#038; then this shell in the background will do everything for us even telnet and so on: print -p \"telnet hostname\".\n\n\nRead Input from User and from Files\n\nRead in a Variable\n\nFrom a user we read with: read var. Then the users can type something in. One should first print something like: print -n \"Enter your favorite haircolor: \";read var; print \"\". The -n suppresses the newline sign.\n\nRead into a File Line for Line\n\nTo get each line of a file into a variable iteratively do:\n\n{ while read myline;do\n   # process $myline\ndone } < filename\nTo catch the output of a pipeline each line at a time in a variable use:\n\nlast | sort | {\nwhile read myline;do\n   # commands\ndone }\n\nSpecial Variables\n\n$# Number of arguments on commandline.\n$? Exit status of last command.\n$$ Process id of current program.\n$! Process id of last backgroundjob or background function.\n$0 Program name including the path if started from another directory.\n$1..n Commandline arguments, each at a time.\n$* All commandline arguments in one string.\n\n\nAction on Success or on Failure of a Command\n\nIf one wants to do a thing only if a command succeded then: command1 &#038;&#038; command2. If the second command has to be performed only if the first one failed, then: command1 || command2.\n\n\nTrivial Calculations\n\nSimpe calculations are done with either a \"let\" in front of it or within (( ... )). One can increment a variable within the (( )) without a \"$\": (( a+=1 )) or let a+=1.\n\n\nNumerical Calculations using \"bc\"\n\nFor bigger caluculations one uses \"bc\" like: $result=$(print \"n=1;for(i=1;i<8;i++)n=i*n;n\"|bc)\n\n\n\"grep\"\n\nSearch for the occurence of a pattern in a file: grep 'pattern' file. If one just wants to know how often soemthing occurs in a file, then: grep -c 'pattern file. This can be used in a script like:\nif [[ $(grep -c 'pattern' file) != 0 ]];then ......;fi. The condition is fullfilled if the pattern was found.\n\n\n\"sed\"\n\nSed means stream line editor. It searches like grep, but is then able to replace the found pattern. If you want to change all occurences of \"poor\" with \"rich\", do: sed -e 's\/poor\/rich\/g' filename. Or what is often seen in software packages, that have to be compiled after getting a propper configuration, is a whole file stuffed with replacements patterns like: \/@foo@\/s;;king;g. This file with inumerable lines like that has to be given to sed with: sed -f sedscript filename. It then precesses each line from file with all the sed commands in the sedscript. (Of course sed can do much more:-))\n\n\n\"awk\"\n\nAwk can find and process a found line with several tools: It can branch, loop, read from files and also print out to files or to the screen, and it can do arithmetics.\nFor example: We have a file with lines like: Fred 300 45 70 but hundreds of them. But some lines have a \"#\" as the first sign of them and we have to omit these ones for both, processing and output. And we want to have lines as output like: 415 Fred where 415 is the sum of 300, 45 and 70. Then we call on awk:\n\nawk '$1 !~ \/^#\/ &#038;&#038; $0 ~ \/[^ ]\/ {print $2+$3+$4,\"\\t\",$1}' filename.\n\nThis ignores lines with a \"#\" at the beginning of the first field and also blank lines. It then prints the desired sum and the $1 ist only printed after a tab. This is the most trivial use of awk only.\nAwk Introduction\n\nExplained by examples rather than by definitons\n\nSyntax for one line awk commands\n\nawk:  awk -Fs                     '\/search\/ {action}' awkvar=$shellvar infile\nnawk: awk -Fs -v awkvar=$shellvar '\/search\/ {action}'                  infile\ngawk: awk -Fs -v awkvar=$shellvar '\/search\/ {action}'                  infile\nKonzept\n\nAwk scannes ascii files or standard input. It can search strings easily and then has a lot of possibilities to process the found lines and output them in the new format. It does not change the input file but sends it's results onto standard output.\n\nawk\/nawk\/gawk\n\nAwk is the orignal awk. Nawk is new_awk and gawk the gnu_awk. The gnu_awk can do most, but is not available everywhere. So best is to use only things which nawk can do, because if that is not installed, then the system is not well anyway.\n\nSearch and Action\n\nSearching happens within \"\/\/\" and actions within \"{}\". The main action is to print.\nReprint all: awk '{print}' infile\nPrint lines that contain \"love\": awk '\/love\/ { print }' infile\nPrint first entry in lines that contain \"money\": awk '\/money\/ { print $1 }' infile\nVariables\n\nAwk does not distinguish between strings and numbers. So one may just put anything into a variable with varname = othervar or varname = \"string\". To get it out of the var just write it's name as a function argument or on the right side of any operator.\n\nMultiline awk in a shell script\n\nAll between '' is in awk. With a=$var awk get's a shell variable.\nThe action is to print varable a and put it into a file.\n\nawk '\n        BEGIN  { print a > &#8220;testfile&#8221; }<br \/>\n&#8216; a=$var<br \/>\nBEGIN { }, { } and end { }<\/p>\n<p>An awk script can have three types of blocks. One of them must be there. The BEGIN{} block is processed before the file is checked. The {} block runs for every line of input and the END{} block is processed after the final line of the input file.<\/p>\n<p>awk &#8216;<br \/>\n        BEGIN    { myvalue = 1700 }<br \/>\n        \/debt\/   { myvalue -= $4  }<br \/>\n        \/want\/   { myvalue += $4  }<br \/>\n        END      { print myvalue  }<br \/>\n&#8216; infile<br \/>\nMatch in a particular field<\/p>\n<p>Awk autosplits a line on whitespace as default. The fields are stored in $1 through $NF and the whole line is in $0. One can match or not match an individual field.<\/p>\n<p>awk &#8216;<br \/>\n        $1 ~ \/fred\/ &#038;&#038; $4 !~ \/ok\/  {<br \/>\n                print &#8220;Fred has not yet paid $3&#8221;<br \/>\n        }<br \/>\n&#8216; infile<br \/>\nFor, If, substr()<\/p>\n<p>Awk can do for() loops like in c++ and has the normal if and while structures. In NR is current line number and in NF the number of fields on the current line.<\/p>\n<p>awk &#8216;<br \/>\n        BEGIN     { count = 0 }<br \/>\n        \/myline\/  {<br \/>\n                    for(i=1;i<=NF;i++){\n                            if(substr($i,3,2) == \"ae\"){\n                                    bla = \"Found it on line: \"\n                                    print bla NR \" in field: \" i\n                                    count++\n\t\t\t    }\n                    }\n        }\n        END       { print \"Found \" count \" instances of it\" }\n' infile\n\nTurn around each word in a file:\n\nawk '\n        {       for(i=1;i<=NF;i++){\n                        len = length($i)\n                        for(j=len;j>0;j&#8211;){<br \/>\n                                char = substr($i,j,1)<br \/>\n                                tmp = tmp char<br \/>\n                        }<br \/>\n                        $i  = tmp<br \/>\n                        tmp = &#8220;&#8221;<br \/>\n                }<br \/>\n                print<br \/>\n        }<br \/>\n&#8216; infile<br \/>\nAwk scripts within a shell script<\/p>\n<p>Extract email addresses from incoming mail. The mail would be guided to the following script from within the ~\/.forward file. This is not an eficient method, but only an example to show serial processing of text. The next example will do the same thing within awk only and will be efficient. The mail comes in over standardinput into the script.<br \/>\nBetween the commands there must be a pipe &#8220;|&#8221;. For continuing on the next line one needs a &#8220;\\&#8221; behind the pipe to escape the invisible newline.<br \/>\n#!\/usr\/bin\/ksh<br \/>\n{ while read line;do<br \/>\n    print &#8211; &#8220;$line&#8221;<br \/>\ndone } |\\<br \/>\ntee -a \/path\/mymailfile |\\<br \/>\nawk &#8216;<br \/>\n         \/^From\/ || \/^Replay\/  {<br \/>\n              for(i=1;i<=NF;i++){\n                  if($i ~ \/@\/){\n                      print $i\n                  }\n              }\n         }\n' |\\\nsed '\n          s\/[<>]\/\/g;<br \/>\n          s\/[()]\/\/g;<br \/>\n          s\/&#8221;\/\/g;<br \/>\n          &#8230;more substitutions for really extracting the email only&#8230;<br \/>\n&#8216; |\\<br \/>\n{ while read addr;do<\/p>\n<p>        if [[ $(grep -c $addr \/path\/antimailfile) -gt 0 ]];then<\/p>\n<p>             mail $addr <<EOF\nPlease dont't send me mail any more!\nEOF\n        else\n             mail $addr <<EOF\nThanks for mailing me. I'll answer as soon as possible!:-))\nEOF\n        fi\n\ndone }\nAll the above in an awk script\n\nnawk -f, while, break, >>, gsub(), getline, system()<\/p>\n<p>With #!\/usr\/bin\/nawk -f the whole script is interpreted intirely as an awk script and no more shell escapes are needed, but one can and has to do everything in awk itself. It&#8217;s nawk because of the getline function.<br \/>\nWhile iterates until the expression becomes wrong or until a break is encountered.<br \/>\nGsub() is for string substitution.<br \/>\nGetline reads in a line each time it es called.<br \/>\nSystem() executes a unix command.<br \/>\n&#8220;>>&#8221; appends to a file.<\/p>\n<p>This script es an example only. For really extracting email addresses several special cases would have to be considered&#8230;<\/p>\n<p>#!\/usr\/bin\/nawk -f<\/p>\n<p># Lines from a mail are dropping in over stdin. Append every line to a<br \/>\n# file before checking anything.<\/p>\n<p>{ print >> &#8220;\/path\/mymailfile&#8221; }<\/p>\n<p># Find lines with with From: or Replay: at beginning.<\/p>\n<p>\/^From:\/ || \/^Replay\/ {<\/p>\n<p># Find fields with @. Iterate over the fields and check for @<\/p>\n<p>    for(i=1;i<=nf;i++){\n\n        if($i ~ \/@\/){\n\n            # Clean the email addresses with gsub()\n\n            gsub(\/[<>()&#8221;]\/,&#8221;&#8221;,$i)<\/p>\n<p>            # Check whether the email address is in the antimailfile<\/p>\n<p>            while( getline antiaddr < \"\/path\/antimailfile\" ){\n\n                # Compare actual address in $i with loaded address\n\n                if($i == antiaddr){\n\n                    # Send a negative mail\n\n                    system(\"mail \" $i \" < \/path\/badmail\")\n\n                    # Now end the while loop \n \n                    break\n\n                }else{\n\n                    # Send a positive mail\n\n                    system(\"mail \" $i \" < \/path\/goodmail\")\n                }\n            }\n        }\n    }\n}\nCalculate on columns and print formated output\n\nIf one has a formated input of number columns one can still split them on white space, but has to consider the format for output with printf()\n\n#!\/usr\/bin\/nawk -f\n\n# Reprintet lines without foo or boo\n\n! \/(foo|boo)\/ { print }\n\n# Rearange and calculate with columns but only on lines with foo or boo\n\n\/(foo|boo)\/ {\n\n        # Extract fields\n\n        mytype = $1\n        var1   = $2\n        var2   = $3\n        var3   = $4\n \n        # Calculate\n\n        if(mytype == \"foo\"){\n\n            var1 *= 10\n            var2 += 20\n            var3  = log(var3)\n        }\n        if(mytype == \"boo\"){\n\n            var1 *= 4\n            var2 += 10\n            var3  = cos(var3)\n        }\n\n        # Print formated output in reverse order\n\n        printf(\"%-4s%10.3f%10.3f%10.3f\\n\",mytype,var3,var2,var1)\n}\nHow to iterate over each word of a shell variable in awk\n\nIn this example there is first a shell variable filled in and then it is given to awk. Awk splits it into an array and then iterates over the array and looks for each word on the current line of a file. If it finds it, it prints the whole line.\n#!\/usr\/bin\/ksh\nvar=\"term1 term2 term3 term4 term5\"\nawk '\n      BEGIN { split(myvar,myarr)  }\n            {\n                 for(val in myarr){\n                     if($0 ~ myarr[val]){\n                         print\n                     }   \n                 }   \n            }  \n' myvar=\"$var\" file\nFunctions\n\nThis example substitutes the first three occurences of \"searchterm\" with a different term in each case and from the fourth case it just prints the line as it is.\nIt should show where to place a function and how to call it.\n\n\n\n#!\/usr\/bin\/nawk -f\nBEGIN{\n        mysub1   = \"first_sub\"\n        mysub2   = \"second_sub\"\n        mysub3   = \"third_sub\"\n        mycount  = 1\n        find     = \"searchterm\"\n}\n{\n        if($0 ~ find){\n                if(mycount == 1){ replace(mysub1); }\n                if(mycount == 2){ replace(mysub2); }\n                if(mycount == 3){ replace(mysub3); }\n                if(mycount >  3){ print; }<br \/>\n                mycount++<br \/>\n         }else{<br \/>\n                print<br \/>\n         }<br \/>\n}<br \/>\nfunction replace(mysub) {<\/p>\n<p>        sub(find,mysub)<br \/>\n        print<br \/>\n        break<br \/>\n}<br \/>\nCGI with gawk<\/p>\n<p>As an example for a CGI script in awk I make one which presents the unix man pages in html.<\/p>\n<p>man.cgi<\/p>\n<p>String functions<\/p>\n<p>sub(regexp,sub)\tSubstitute sub for regexp in $0<br \/>\nsub(regexp,sub,var)\tSubstitute sub for regexp in var<br \/>\ngsub(regexp,sub)\tGlobally substitute sub for regexp in $0<br \/>\ngsub(regexp,sub,var)\tGlobally substitute sub for regexp in var<br \/>\nsplit(var,arr)\tSplit var on white space into arr<br \/>\nsplit(var,arr,sep)\tSplit var on white space into arr on sep as separator<br \/>\nindex(bigvar,smallvar)\tFind index of smallvar in bigvar<br \/>\nmatch(bigvar,expr)\tFind index for regexp in bigvar<br \/>\nlength(var)\tNumber of characters in var<br \/>\nsubstr(var,num)\tExtract chars from posistion num to end<br \/>\nsubstr(var,num1,num2)\tExtract chars from num1 through num2<br \/>\nsprintf(format,vars)\tFormat vars to a string<br \/>\nWhen to use awk, when to use perl?<\/p>\n<p>Perl can do 100 times more than awk can, but awk is present on any standard unix system, where perl first has to be installed. And for short commands awk seems to be more practical. The autosplit mode of perl splits into pieces called: $F[0] through $F[$#F] which is not so nice as $1 through $NF where awk retains the whole line in $0 at the same time.<br \/>\nTo get the first column of any file in awk and in perl:<\/p>\n<p>awk &#8216;{print $1}&#8217; infile<br \/>\nperl -nae &#8216;print $F[0],&#8221;\\n&#8221;;&#8217; infile <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Principle of Script<\/p>\n<p>Defining the Shell Type<\/p>\n<p>To make a ksh script (which is a ksh program) crate a new file with a starting line like: #!\/usr\/bin\/ksh It is important that the path to the ksh is propper and that the line doesn not have more than 32 characters. The shell from which you are [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[47],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3453"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3453"}],"version-history":[{"count":3,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3453\/revisions"}],"predecessor-version":[{"id":3456,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3453\/revisions\/3456"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}