Depends on where, how often, why etc you do this, but it wouldn't hurt to put it in a script.
Anyhow you could do something like this to print in defined order. By this
approach you can also choose to only print a selected few. E.g. only 1 and 3:
One liner:
awk -v order=312 \
'/^/{ln[NR]=$0}END{split(order,a,"");
for(i in a)printf("%s\n",ln[a[i]]);}' \
sample.txt
Or more easy to read:
/^/{
ln[NR] = $0
}
END{
split(order,a,"");
for(i in a)
printf("%s\n",ln[a[i]]);
}
For the split you could add some delimiter if more then 9 lines.
E.g.:
split(order,a,"-");
# and call by:
awk -v order=3-13-21-12-2 ...
Or to support multiple:
if (order ~ /-/) split(order, a, "-"); # order has "-", split
else if (order ~ /\./) split(order, a, "."); # order has ".", split
else if (order ~/:/) split(order, a, ":"); # order has ":", split
else split(order, a, ""); # none presume numbers split all
You could also choose to match lines as in:
BEGIN {
i = 0;
}
/^\s*Acct-Status-Type/ {ln[++i] = $0 }
/^\s*User-Name/ {ln[++i] = $0 }
/^\s*Event-Timestamp/ {ln[++i] = $0 }
END {
if (order ~ /-/) split(order, a, "-");
else if (order ~ /\./) split(order, a, ".");
else if (order ~/:/) split(order, a, ":");
else split(order, a, "")
for (i in a)
printf("%s\n", ln[a[i]]);
}
Edit:
For last sample this would probably be better. (Also updated the split):
/^\s*Acct-Status-Type/ {ln[1] = $0 }
/^\s*User-Name/ {ln[2] = $0 }
/^\s*Event-Timestamp/ {ln[3] = $0 }
END {
if (split(order, a, "-|:|,| |\\.") == 1) # Space require quoting of arg.
split(order, a, "")
for (i in a)
printf("%s\n", ln[a[i]]);
}
sed '1!G;h;$!d'perl -e 'print reverse <>'sort -r?