File: //usr/share/awk/dpkg-awk.awk
BEGIN {
FS="\n"
RS=""
ORS=""
help="\
-f <file> Read <file>, instead of the default\n\
--filename =? <file> /var/lib/dpkg/status.\n\
\n\
-d Each time this is specified, increase\n\
--debug the debugging output.\n\
\n\
-s <field list> Store the output, and sort it based on\n\
--sort =? <field list> these fields. Each field is separated\n\
by <space> or <comma>.\n\
\n\
-rs <output sep> Output this string at the end of each\n\
--rec_sep <output sep> paragraph.\n\
\n\
-n <field list> List the fields that should be treated\n\
--numeric <field list> numerically for sorting purposes.\n\
"
opt_list = ":n :f #d :s :rs :numeric :filename #debug :sort :rec_sep :outform :of"
opt_link = "n=numeric f=filename d=debug s=sort rs=rec_sep of=outform"
options["rs"] = "\n"
options["of"] = "normal"
option_parse(opt_list, opt_link, help, ARGC, ARGV)
for (c = 1; c <= ARGC; c++) {
if (length(ARGV[c])) {
itm = ARGV[c]
if ( q == 2) {
}
if (q == 1) {
if (itm == "--") { q = 2 } else {
if (match(itm, /^\^/)) {
#
# Output *ALL* fields, but these.
#
sub(/^\^/, "", itm)
if (!(1 SUBSEP tolower(itm) in outf)) {
if(outf[1,0] >= 0) {
outf[1,0]++
outf[1,outf[1,0]] = itm
outf[1,tolower(itm)] = ""
outf[0] = -1
}
}
} else {
#
# Output only these fields.
#
if (!(itm in outf)) {
if(outf[0] >= 0) {
outf[0]++
outf[outf[0]] = itm
outf[itm] = ""
outf[1,0] = -1
}
}
}
}
}
if (q == 0) {
#
# Perform regex matchs on these fields.
#
if (itm == "--") { q = 1 } else {
if ( p = index(itm,":")){
ndx = tolower(substr(itm,1, p - 1))
val = substr(itm, p + 1)
regx[ndx] = val
}
}
}
# print "\n"
}
}
split(options["numeric"], numeric_fields, " ")
for (c = 1; c <= outf[0]; c++)
delete outf[outf[c]]
if (options["debug"] >= 1)
for (a in outf)
print "outf[" a "]=" outf[a] "\n"
if (options["debug"] >= 1)
print "ARGV[0]='" ARGV[0] "'\n"
delete ARGV
if (options["debug"] >= 1)
for (a in options)
print "options[" a "]='" options[a] "'\n"
ARGV[1] = "/var/lib/dpkg/status"
if ("filename" in options) ARGV[1] = options["filename"]
num_fields=0
sort_fields["a"]=0
}
function my_split(input, output,
a, b, fields, save0)
{
delete output
delete fields
save0 = $0
$0 = input
num_fields = split(input, fields, "\n")
b = 0
if (options["debug"] >= 2) {
print "my_split\n"
for (a = 1; a <= num_fields; a++)
print "fields[" a "]='" fields[a] "'\n"
print "done\n"
}
for (a = 1; a <= num_fields; a++) {
if (match(fields[a], /^[^ ].*:.*$/)) {
split(fields[a], fld, ":")
b = b + 1
output[1,++output[1,0]] = fld[1]
output[1,tolower(fld[1])] = ""
sub(/^[^:]*: */,"",fields[a])
if(a in numeric_fields)
fields[a] = 0 + fields[a]
output[tolower(fld[1])] = fields[a]
} else {
q = output[tolower(fld[1])]
output[tolower(fld[1])] = q FS fields[a]
delete fields[a]
}
}
$0 = save0
return num_fields
}
function my_outrec(fields, outf,
c)
{
if(outf[0] > 0) {
if (options["debug"] >= 1)
print "normal\n"
for (c = 1; c <= outf[0]; c++)
if ( tolower(outf[c]) in fields )
print outf[c] ": " fields[tolower(outf[c])] "\n"
} else {
if(outf[1,0] > 0) {
if (options["debug"] >= 1)
print "inverted " fields[1,0] "\n"
for (c = 1; c <= fields[1,0]; c++) {
if (options["debug"] >= 1)
print "fields[1," c "]='" 1 SUBSEP tolower(fields[1,c]) "'\n"
if (!(1 SUBSEP tolower(fields[1,c]) in outf )) {
if(options["outform"] == "normal")
print fields[1,c] ": " fields[tolower(fields[1,c])] "\n"
}
}
} else {
if (options["debug"] >= 1)
print "all\n"
for (c = 1; c <= fields[1,0]; c++)
print fields[1,c] ": " fields[tolower(fields[1,c])] "\n"
}
}
print options["rec_sep"]
}
function my_compare(mthd, i, j,
c, fld)
{
if (mthd == 0) {
if(num_fields) {
my_split(i, fld_i)
my_split(j, fld_j)
for(c = 1; c <= num_fields; c++) {
fld = tolower(sort_fields[c])
if(options["debug"] >=2)
print "sort fld=" fld "\n"
if (options["debug"] >= 2) {
print "\tPackage[" fld "]='" fld_i[fld] "' "
print "\tPackage[" fld "]='" fld_j[fld] "' "
}
if(match(fld, /.*:n$/)) {
gsub(/:n$/, fld)
if (fld_i[fld]+0 < fld_j[fld]+0)
return -1
if (fld_i[fld]+0 > fld_j[fld]+0)
return 1
} else {
if (fld_i[fld] < fld_j[fld])
return -1
if (fld_i[fld] > fld_j[fld])
return 1
}
}
}
}
if (options["debug"] >= 2) print "-1\n"
return 0
}
function my_sort(line, outf,
num_fields, c)
{
qsort(0, line, 1, mtchs)
num_fields = split(options["sort"], sort_fields, "[ ,]")
qsort(0, line, 1, mtchs)
delete sort_fields
for (c = 1; c <= mtchs; c++){
my_split(line[c], fields)
my_outrec(fields, outf)
}
}
function readline( Old_RS, line)
{
Old_RS=RS
RS="\n"
"read; echo $REPLY" | getline line
close("read; echo $REPLY")
RS=Old_RS
return line
}
#
# Begin of script
#
{
my_split($0, fields)
for (c in regx)
if ( match(fields[c], regx[c])==0)
next
my_split($0, fields)
# test = readline()
# print "test='" test "'\n"
if (options["debug"] >= 1) for (a in fields) print "fields[" a "]=" fields[a] "\n"
if ("sort" in options) {
line[++mtchs] = $0
if (options["debug"] >= 1) print mtchs " "
} else
my_outrec(fields, outf)
}
END {
print "\n"
if ("sort" in options)
my_sort(line, outf)
}
#
#
# qsort functions
#
#
function middle(mthd, x,y,z) #return middle of 3
{
ret_xy = my_compare(mthd, x, y)
ret_zy = my_compare(mthd, z, y)
if (ret_xy <= 0 ) {
if ( ret_zy >= 0 ) return y
if ( my_compare(mthd, z, x) < 0 ) return x
return z
}
if ( my_compare(mthd, z, x) >= 0 ) return x
if ( ret_zy < 0 ) return y
return z
}
# recursive quicksort
function qsort(mthd, A, left, right ,i , j, pivot, hold)
{
pivot = middle(mthd, A[left], A[int((left + right)/2)], A[right])
i = left
j = right
while ( i <= j ) {
while (my_compare(mthd, A[i], pivot) < 0) i++
while (my_compare(mthd, A[j], pivot) > 0) j--
if ( i <= j ) {
hold = A[i]
A[i++] = A[j]
A[j--] = hold
}
}
if ( j - left > 0 ) qsort(mthd, A, left, j)
if ( right - i > 0 ) qsort(mthd, A, i, right)
}