Using awk to print all columns from the nth to the

2019-01-03 00:29发布

This line worked until I had whitespace in the second field.

svn status | grep '\!' | gawk '{print $2;}' > removedProjs

is there a way to have awk print everything in $2 or greater? ($3, $4.. until we don't have anymore columns?)

I suppose I should add that I'm doing this in a Windows environment with Cygwin.

标签: linux awk
24条回答
劫难
2楼-- · 2019-01-03 01:21
echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

this one uses awk to print all except the last field

查看更多
狗以群分
3楼-- · 2019-01-03 01:21

I want to extend the proposed answers to the situation where fields are delimited by possibly several whitespaces –the reason why the OP is not using cut I suppose.

I know the OP asked about awk, but a sed approach would work here (example with printing columns from the 5th to the last):

  • pure sed approach

    sed -r 's/^\s*(\S+\s+){4}//' somefile
    

    Explanation:

    • s/// is used the standard way to perform substitution
    • ^\s* matches any consecutive whitespace at the beginning of the line
    • \S+\s+ means a column of data (non-whitespace chars followed by whitespace chars)
    • (){4} means the pattern is repeated 4 times.
  • sed and cut

    sed -r 's/^\s+//; s/\s+/\t/g' somefile | cut -f5-
    

    by just replacing consecutive whitespaces by a single tab;

  • tr and cut: tr can also be used to squeeze consecutive characters with the -s option.

    tr -s [:blank:] <somefile | cut -d' ' -f5-
    
查看更多
劳资没心,怎么记你
4楼-- · 2019-01-03 01:23

This was irritating me so much, I sat down and wrote a cut-like field specification parser, tested with GNU Awk 3.1.7.

First, create a new Awk library script called pfcut, with e.g.

sudo nano /usr/share/awk/pfcut

Then, paste in the script below, and save. After that, this is how the usage looks like:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-4"); }'
t1 t2 t3 t4

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("2-"); }'
t2 t3 t4 t5 t6 t7

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk -f pfcut --source '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

To avoid typing all that, I guess the best one can do (see otherwise Automatically load a user function at startup with awk? - Unix & Linux Stack Exchange) is add an alias to ~/.bashrc; e.g. with:

$ echo "alias awk-pfcut='awk -f pfcut --source'" >> ~/.bashrc
$ source ~/.bashrc     # refresh bash aliases

... then you can just call:

$ echo "t1 t2 t3 t4 t5 t6 t7" | awk-pfcut '/^/ { pfcut("-2,4,6-"); }'
t1 t2 t4 t6 t7

Here is the source of the pfcut script:

# pfcut - print fields like cut
#
# sdaau, GNU GPL
# Nov, 2013

function spfcut(formatstring)
{
  # parse format string
  numsplitscomma = split(formatstring, fsa, ",");
  numspecparts = 0;
  split("", parts); # clear/initialize array (for e.g. `tail` piping into `awk`)
  for(i=1;i<=numsplitscomma;i++) {
    commapart=fsa[i];
    numsplitsminus = split(fsa[i], cpa, "-");
    # assume here a range is always just two parts: "a-b"
    # also assume user has already sorted the ranges
    #print numsplitsminus, cpa[1], cpa[2]; # debug
    if(numsplitsminus==2) {
     if ((cpa[1]) == "") cpa[1] = 1;
     if ((cpa[2]) == "") cpa[2] = NF;
     for(j=cpa[1];j<=cpa[2];j++) {
       parts[numspecparts++] = j;
     }
    } else parts[numspecparts++] = commapart;
  }
  n=asort(parts); outs="";
  for(i=1;i<=n;i++) {
    outs = outs sprintf("%s%s", $parts[i], (i==n)?"":OFS); 
    #print(i, parts[i]); # debug
  }
  return outs;
}

function pfcut(formatstring) {
  print spfcut(formatstring);
}
查看更多
聊天终结者
5楼-- · 2019-01-03 01:23

This awk function returns substring of $0 that includes fields from begin to end:

function fields(begin, end,    b, e, p, i) {
    b = 0; e = 0; p = 0;
    for (i = 1; i <= NF; ++i) {
        if (begin == i) { b = p; }
        p += length($i);
        e = p;
        if (end == i) { break; }
        p += length(FS);
    }
    return substr($0, b + 1, e - b);
}

To get everything starting from field 3:

tail = fields(3);

To get section of $0 that covers fields 3 to 5:

middle = fields(3, 5);

b, e, p, i nonsense in function parameter list is just an awk way of declaring local variables.

查看更多
闹够了就滚
6楼-- · 2019-01-03 01:26
awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'

My answer is based on the one of VeeArr, but I noticed it started with a white space before it would print the second column (and the rest). As I only have 1 reputation point, I can't comment on it, so here it goes as a new answer:

start with "out" as the second column and then add all the other columns (if they exist). This goes well as long as there is a second column.

查看更多
够拽才男人
7楼-- · 2019-01-03 01:28

If you want formatted text, chain your commands with echo and use $0 to print the last field.

Example:

for i in {8..11}; do
   s1="$i"
   s2="str$i"
   s3="str with spaces $i"
   echo -n "$s1 $s2" | awk '{printf "|%3d|%6s",$1,$2}'
   echo -en "$s3" | awk '{printf "|%-19s|\n", $0}'
done

Prints:

|  8|  str8|str with spaces 8  |
|  9|  str9|str with spaces 9  |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |
查看更多
登录 后发表回答