Использование awk для печати всех столбцов с n-го до последнего

прямо сейчас у меня есть эта строка, и она работала, пока у меня не было пробела во втором поле.

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

Есть ли способ распечатать awk все в $2 или выше? ($ 3, $4.. до тех пор, пока у нас больше нет столбцов?)

Я полагаю, я должен добавить, что я делаю это в среде Windows с Cygwin.

Ответ 1

будет печатать все, кроме первой колонки:

awk '{$1=""; print $0}' somefile

будет печатать все, кроме двух первых столбцов:

awk '{$1=$2=""; print $0}' somefile

Ответ 2

Существует дублированный вопрос с более простым ответом с использованием cut:

 svn status |  grep '\!' | cut -d\  -f2-

-d указывает разделитель (пробел), -f указывает список столбцов (все начиная со второго)

Ответ 3

Вы можете использовать цикл for-loop для печати через поля от $2 до $NF (встроенная переменная, которая представляет количество полей в строке).

Изменить: Поскольку "print" добавляет новую строку, вам нужно буферизировать результаты:

awk '{out=""; for(i=2;i<=NF;i++){out=out" "$i}; print out}'

В качестве альтернативы используйте printf:

awk '{for(i=2;i<=NF;i++){printf "%s ", $i}; printf "\n"}'

Ответ 4

awk '{out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}'

Мой ответ основан на на VeeArr, но я заметил, что он начался с пробела, прежде чем он напечатает второй столбец (и остальные). Поскольку у меня только 1 точка репутации, я не могу ее прокомментировать, так что здесь это новый ответ:

начните с "out" как второй столбец, а затем добавьте все остальные столбцы (если они существуют). Это идет хорошо, пока есть второй столбец.

Ответ 5

Я лично пробовал все ответы, упомянутые выше, но большинство из них были немного сложными или просто неправильными. Самый простой способ сделать это с моей точки зрения:

awk -F" " '{ for (i=4; i<=NF; i++) print $i }'
  • Где -F "определяет разделитель для awk для использования. В моем случае это пробел, который также является разделителем по умолчанию для awk. Это означает, что -F" " можно игнорировать.

  • Где NF определяет общее количество полей/столбцов. Поэтому цикл будет начинаться с 4-го поля до последнего поля/столбца.

  • Где $N извлекает значение N-го поля. Поэтому print $i будет печатать текущее поле/столбец на основе количества циклов.

Ответ 6

Это меня так сильно раздражало, я сел и написал парсер синтаксического анализа cut, проверенный с помощью GNU Awk 3.1.7.

Сначала создайте новую библиотеку Awk script, называемую pfcut, например,

sudo nano /usr/share/awk/pfcut

Затем вставьте script ниже и сохраните. После этого это выглядит так:

$ 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

Чтобы избежать ввода всего этого, я думаю, что самое лучшее, что можно сделать (см. иначе Автоматически загружать пользовательскую функцию при запуске с awk? - Unix и Linux Stack Exchange) добавляет псевдоним ~/.bashrc; например с:

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

... тогда вы можете просто позвонить:

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

Вот источник 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);
}

Ответ 7

Будет ли это работать?

awk '{print substr($0,length($1)+1);}' < file

Он оставляет некоторые пробелы впереди, хотя.

Ответ 8

Распечатка столбцов, начинающихся С# 2 (выход не будет иметь конечного пространства в начале):

ls -l | awk '{sub(/[^ ]+ /, ""); print $0}'

Ответ 9

echo "1 2 3 4 5 6" | awk '{ $NF = ""; print $0}'

для этого используется awk для печати всех, кроме последнего поля

Ответ 10

Большинство решений с awk оставляют пространство. Варианты здесь избегают этой проблемы.

Вариант 1

Простое решение разреза (работает только с одиночными разделителями):

command | cut -d' ' -f3-

Вариант 2

Принудительное перевычисление awk иногда удаляет добавленное начальное пространство (OFS), оставленное путем удаления первых полей (работает с некоторыми версиями awk):

command | awk '{ $1=$2="";$0=$0;} NF=NF'

Вариант 3

Печать каждого поля, отформатированного с помощью printf, даст больше контроля:

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in"|awk -v n=2 '{ for(i=n+1;i<=NF;i++) printf("%s%s",$i,i==NF?RS:OFS);}'
3 4 5 6 7 8

Однако все предыдущие ответы изменяют все повторяющиеся FS между полями в OFS. Давайте построим пару вариантов, которые этого не делают.

Вариант 4 (рекомендуется)

Цикл с sub для удаления полей и разделителей спереди.
И используя значение FS вместо пространства (которое можно было бы изменить).
Более портативен и не вызывает смены FS на OFS: ПРИМЕЧАНИЕ. ^[FS]* должен принимать вход с ведущими пробелами.

$ in='    1    2  3     4   5   6 7     8  '
$ echo "$in" | awk '{ n=2; a="^["FS"]*[^"FS"]+["FS"]+";
  for(i=1;i<=n;i++) sub( a , "" , $0 ) } 1 '
3     4   5   6 7     8

Вариант 5

Вполне возможно построить решение, которое не добавляет лишние (ведущие или конечные) пробелы, и сохраняет существующие пробелы с помощью функции gensub из GNU awk, так как это:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          { print(gensub(a""b""c,"",1)); }'
3     4   5   6 7     8 

Он также может использоваться для замены группы полей с учетом count n:

$ echo '    1    2  3     4   5   6 7     8  ' |
  awk -v n=2 'BEGIN{ a="^["FS"]*"; b="([^"FS"]+["FS"]+)"; c="{"n"}"; }
          {
            d=gensub(a""b""c,"",1);
            e=gensub("^(.*)"d,"\\1",1,$0);
            print("|"d"|","!"e"!");
          }'
|3     4   5   6 7     8  | !    1    2  !

Конечно, в этом случае OFS используется для разделения обеих частей линии, а оставшееся пробел полей по-прежнему печатается.

ПРИМЕЧАНИЕ. [FS]* используется, чтобы разрешать ведущие пробелы в строке ввода.

Ответ 11

Это то, что я предпочел из всех рекомендаций:

Печать с шестого на последний столбец.

ls -lthr | awk '{out=$6; for(i=7;i<=NF;i++){out=out" "$i}; print out}'

или

ls -lthr | awk '{ORS=" "; for(i=6;i<=NF;i++) print $i;print "\n"}'

Ответ 12

Если вам нужны конкретные столбцы, напечатанные с помощью произвольного делиметра:

awk '{print $3 "  " $4}'

col # 3 col # 4

awk '{print $3 "anything" $4}'

Col ​​# 3anythingcol # 4

Итак, если у вас есть пробел в столбце, это будет два столбца, но вы можете подключить его к любому разделителю или без него.

Ответ 13

Решение Perl:

perl -lane 'splice @F,0,1; print join " ",@F' file

Эти параметры командной строки используются:

  • -n перемещаться по каждой строке входного файла, не печатать автоматически каждую строку

  • -l удаляет символы новой строки перед обработкой и добавляет их обратно

  • -a режим автосплит - разделение входных строк на массив @F. По умолчанию разделение на пробелы

  • -e выполнить код perl

splice @F,0,1 чисто удаляет столбец 0 из массива @F

join " ",@F объединяет элементы массива @F, используя пространство между каждым элементом


Решение Python:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[1:]) + '\n') for line in sys.stdin]" < file

Ответ 14

awk '{ for(i=3; i<=NF; ++i) printf $i""FS; print "" }'

lauhub предложили это правильное, простое и быстрое решение здесь

Ответ 15

Perl:

@m=`ls -ltr dir | grep ^d | awk '{print \$6,\$7,\$8,\$9}'`;
foreach $i (@m)
{
        print "$i\n";

}

Ответ 16

Это будет работать, если вы используете Bash, и вы можете использовать столько "х", сколько вы хотите отменить, и игнорирует несколько пробелов, если они не экранированы.

while read x b; do echo "$b"; done < filename

Ответ 17

Если вы не хотите переформатировать часть строки, которую вы не отрубаете, лучшее решение, о котором я могу думать, написано в моем ответе в:

Как распечатать все столбцы после определенного номера с помощью awk?

Он отбрасывает то, что находится перед данным номером поля N, и печатает всю оставшуюся часть строки, включая номер поля N и поддерживая исходный интервал (он не переформатируется). Это не означает, что строка поля появляется также где-то еще в строке.

Определите функцию:

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

И используйте его следующим образом:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

Результат поддерживает все, включая конечные пробелы

В вашем конкретном случае:

svn status | grep '\!' | fromField 2 > removedProjs

Если ваш файл/поток не содержит символов новой строки в середине строк (вы можете использовать другой разделитель записи), вы можете использовать:

awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Первый случай выйдет из строя только в файлах/потоках, содержащих редкий шестнадцатеричный char номер 1

Ответ 18

Если вы хотите отформатировать текст, соедините свои команды с эхом и используйте $0 для печати последнего поля.

Пример:

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

Печать

|  8|  str8|str with spaces 8  |
|  9|  str9|str with spaces 9  |
| 10| str10|str with spaces 10 |
| 11| str11|str with spaces 11 |

Ответ 19

Эта функция awk возвращает подстроку $0, которая включает в себя поля от begin до 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);
}

Чтобы получить все, начиная с поля 3:

tail = fields(3);

Чтобы получить раздел $0, который охватывает поля с 3 по 5:

middle = fields(3, 5);

b, e, p, i бессмысленность в списке параметров функции - это просто способ awk объявления локальных переменных.

Ответ 20

ls -la | awk '{o=$1" "$3; for (i=5; i<=NF; i++) o=o" "$i; print o }'

from этот ответ не плох, но естественный интервал ушел.
Затем сравните его с этим:

ls -la | cut -d\  -f4-

Тогда вы увидите разницу.

Даже ls -la | awk '{$1=$2=""; print}', основанный на ответе, который был проголосован лучше всего, пока не сохраняет форматирование.

Таким образом, я бы использовал следующее, и он также допускает явные избирательные столбцы в начале:

ls -la | cut -d\  -f1,4-

Обратите внимание, что каждое пространство также подсчитывается для столбцов, поэтому, например, в нижеследующем, столбцы 1 и 3 пусты, 2 - INFO, а 4:

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f1,3

$ echo " INFO  2014-10-11 10:16:19  main " | cut -d\  -f2,4
INFO 2014-10-11
$

Ответ 21

Примеры Awk выглядят сложными здесь, вот простой синтаксис оболочки Bash:

command | while read -a cols; do echo ${cols[@]:1}; done

Где 1 - ваш n-й столбец с 0.


Пример

Учитывая это содержимое файла (in.txt):

c1
c1 c2
c1 c2 c3
c1 c2 c3 c4
c1 c2 c3 c4 c5

вот результат:

$ while read -a cols; do echo ${cols[@]:1}; done < in.txt 

c2
c2 c3
c2 c3 c4
c2 c3 c4 c5

Ответ 22

Мне не понравилось ни одно из представленных здесь решений awk, потому что я хотел извлечь первые несколько столбцов, а затем распечатать остальные, поэтому вместо этого я обратился к perl. Следующий код извлекает первые два столбца и отображает остальные как:

echo -e "a  b  c  d\te\t\tf g" | \
  perl -ne 'my @f = split /\s+/, $_, 3; printf "first: %s second: %s rest: %s", @f;'

Преимущество по сравнению с perl решением от Chris Koknat состоит в том, что на самом деле только первые n элементов отделяются от входной строки; остальная часть струны вообще не расщепляется и остается полностью неповрежденной. Мой пример демонстрирует это с помощью сочетания пробелов и вкладок.

Чтобы изменить количество столбцов, которые нужно извлечь, замените 3 в примере на n + 1.