Awk: Difference between revisions

From Leo's Notes
This page was last edited on 12 September 2019, at 03:16.
m Text replacement - "Category:Linux{{Navbox Linux}}" to "{{Navbox Linux}}Category:Linux"
Imported WP content from http://leo.steamr.com/2011/01/converting-filenames-to-lower-case/
Line 36: Line 36:
I wanted to sort size in reverse order, but in order to do that properly, the value from du needs to be in kilobytes. I also didn't want to run this through du again just to get the human readable value. So, I did this:
I wanted to sort size in reverse order, but in order to do that properly, the value from du needs to be in kilobytes. I also didn't want to run this through du again just to get the human readable value. So, I did this:


<syntaxhighlight lang="bash" line start="1" enclose="div">
{{highlight|lang=terminal|code=
du -s ./*/ ./*/*/ ./*/*/*/ \  
<nowiki>
$ du -s ./*/ ./*/*/ ./*/*/*/ \  
   | sort -rn \  
   | sort -rn \  
   | awk 'BEGIN { \  
   | awk 'BEGIN { \  
Line 49: Line 50:
       print y type[i+2]" "$2 \  
       print y type[i+2]" "$2 \  
   }'  
   }'  
</syntaxhighlight>
</nowiki>
}}


If you want to count using bytes instead of kilobytes, just add K to the split function and replace i=4 with i=5.
If you want to count using bytes instead of kilobytes, just add K to the split function and replace i=4 with i=5.
Line 55: Line 57:


== Convert {{code|ps}} Elapsed Time to Seconds ==
== Convert {{code|ps}} Elapsed Time to Seconds ==
To convert the elapsed time (in [http://pubs.opengroup.org/onlinepubs/009696799/utilities/ps.html POSIX locale] formatted as {{code|[[dd-]hh:]mm:ss}}) to seconds using awk:
To convert the elapsed time (in [http://pubs.opengroup.org/onlinepubs/009696799/utilities/ps.html POSIX locale] formatted as {{code|<nowiki>[[dd-]hh:]mm:ss</nowiki>}}) to seconds using awk:


<syntaxhighlight lang="bash">
{{highlight|lang=bash|code=
<nowiki>
Elapsed=`ps -p $Pid -o etime=`
Elapsed=`ps -p $Pid -o etime=`
Elapsed=`echo $Elapsed | tr - : | tr : ' '`  
Elapsed=`echo $Elapsed | tr - : | tr : ' '`  
Seconds=`echo $Elapsed | awk '  
Seconds=`echo $Elapsed | awk '  
NF == 2 { print ($1 * 60) + $2 }  
NF == 2 { print ($1 * 60) + $2 }  
Line 65: Line 69:
NF == 4 { print ((((($1 * 24) + $2) * 60) + $3) * 60) + $4 }  
NF == 4 { print ((((($1 * 24) + $2) * 60) + $3) * 60) + $4 }  
{}'`  
{}'`  
echo $Seconds
echo $Seconds
</syntaxhighlight>
</nowiki>
}}


For example, a process running for {{code|66-00:12:58}} has been running for 5703178 seconds. The Awk command will match how many columns were found and then do the proper calculation.
For example, a process running for {{code|66-00:12:58}} has been running for 5703178 seconds. The Awk command will match how many columns were found and then do the proper calculation.
Line 73: Line 79:
To grab a specific section from a .spec file (where sections begin with {{code|%}}):
To grab a specific section from a .spec file (where sections begin with {{code|%}}):


<syntaxhighlight lang="bash">


{{highlight|lang=bash|code=
<nowiki>
if [ $# -ne 2 ] ; then
if [ $# -ne 2 ] ; then
echo "Usage: $0 file.spec section"
echo "Usage: $0 file.spec section"
Line 100: Line 107:
}
}
}
}
</nowiki>
}}
== String Upper/Lower Casing ==
There is a {{code|tolower()}} function that can lowercase an entire string.
You could use this to mass-rename a bunch of files to lower case for instance.
{{highlight|lang=terminal|code=
## Lower case every file in the current directory
$ for i in `ls` ; do mv $i `echo $i | awk '{print tolower($1)}'`; done


</syntaxhighlight>
## Alternatively, use `tr 'A-Z' 'a-z'` to do the lowercasing.
$ for i in `ls` ; do mv $i `echo $i | tr 'A-Z 'a-z'`; done
}}





Revision as of 03:16, 12 September 2019

Do something until a line match

With Awk, it's easy to do something for each matching line using the regex matching operator.


Print every line before a line match

Simple awk code:

# cat list.txt | awk '/PATTERN/ { exit } { print $0 }'

Basically, the code does: match against the given pattern. If it matches, awk exits. Otherwise, print the line and continue.

Print line number on matching lines

To print the number of lines up to a matching line, we do something similar to the previous example but now we keep an accumulator (n):

awk 'BEGIN { n = 0 } /PATTERN/ { print n; exit } { n++ }'

Eg: Suppose I have a file with the contents:

leo
spoon
cake
fork

To find the number of lines up until 'cake', do:

# cat list.txt | awk 'BEGIN { n = 0 } /cake/ { print n; exit } { n++ }'


Convert Number as Bytes to Human Readable Value

I wanted to sort size in reverse order, but in order to do that properly, the value from du needs to be in kilobytes. I also didn't want to run this through du again just to get the human readable value. So, I did this:

$ du -s ./*/ ./*/*/ ./*/*/*/ \ 
   | sort -rn \ 
   | awk 'BEGIN { \ 
      split("KB MB GB TB PB", type) \ 
   } \ 
   { \ 
      y = 0; \                                                                                                  
      x = $1; \ 
      for (i = 4; y &lt; 1 ; i--) \ 
         y = x / (2 ** (10 * i)); \ 
      print y type[i+2]" "$2 \ 
   }'

If you want to count using bytes instead of kilobytes, just add K to the split function and replace i=4 with i=5.


Convert ps Elapsed Time to Seconds

To convert the elapsed time (in POSIX locale formatted as [[dd-]hh:]mm:ss) to seconds using awk:

Elapsed=`ps -p $Pid -o etime=`
Elapsed=`echo $Elapsed | tr - : | tr : ' '` 

Seconds=`echo $Elapsed | awk ' 
	NF == 2 { print ($1 * 60) + $2 } 
	NF == 3 { print ((($1 * 60) + $2) * 60) + $3 } 
	NF == 4 { print ((((($1 * 24) + $2) * 60) + $3) * 60) + $4 } 
	{}'` 
	
echo $Seconds

For example, a process running for 66-00:12:58 has been running for 5703178 seconds. The Awk command will match how many columns were found and then do the proper calculation.

Get a Text Section

To grab a specific section from a .spec file (where sections begin with %):


if [ $# -ne 2 ] ; then
	echo "Usage: $0 file.spec section"
	exit
fi

Section="$2"

cat $1 | awk -v Section="$Section" '
BEGIN {
	InSection=false
} 
/^%.*/ { 
	if ($0 ~ Section) {
		InSection=1
	} else {
		InSection=0
	}

	next
}
{
	if (InSection) {
		print $0
	}
}

String Upper/Lower Casing

There is a tolower() function that can lowercase an entire string.

You could use this to mass-rename a bunch of files to lower case for instance.

## Lower case every file in the current directory
$ for i in `ls` ; do mv $i `echo $i