3

Я пишу следующий сценарий awk:

% echo /var/sysconfig/network/my_functions  alpha beta gama  | \
      awk -v word=alpha '$2  == word { print $0 }'

как сказать awk, что я хочу напечатать всю строку, кроме $ 1 (/var/sysconfig/network/my_functions PATH), поэтому я получу следующее:

alpha beta gama

вместо

/var/sysconfig/network/my_functions alpha beta gama

примечание: содержимое строки может быть любым и не ограничено количеством строк / слов

7 ответов7

5

Если вы установите « $1 на "" вы покинете пробел. Если вы не хотите этого делать, вы должны перебирать поля:

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

Редактировать: исправлено в комментарии Жиля.

Еще один способ сделать то же самое:

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

Каким-то образом я думаю, что это было бы намного проще и интуитивнее сделать с помощью команды cut:

echo /var/sysconfig/network/my_functions  alpha beta gama | cut -d' ' -f 2-

Единственная проблема заключается в том, что cut не поддерживает несколько различных типов пробелов одновременно для разделителей. Так что если у вас есть пробелы или табуляции, это не сработает.

1

Это (несколько сложное) решение, которое несколько похоже на ответ Жиля,

  • не выводит пробел в начале строки,
  • правильно обрабатывает случай, когда строка ввода начинается с пробела, и
  • сохраняет пробелы между полями.
awk -v word=alpha '
    $2 == word {
        i = index($0, $1)               # Find $1 within $0 (the line).
        if (i > 0) {                    # Sanity check; should always be true.
                i = i + length($1)      # Find space after $1.
                temp = substr($0, i)
                i = index(temp, $2)     # Find $2 in remainder of line.
                if (i > 0) {            # Sanity check; should always be true.
                        print substr(temp, i)
                }
        }
    }'

Я считаю, что комментарии в строке объясняют это довольно хорошо.  Мы находим позицию $1 в строке (помните, я явно не предполагаю, что это в начале).  Затем, в ответ на вопрос Жиля, мы убираем $1 (и пробел перед ним, если есть) с линии.  Затем найдите позицию $2 в оставшейся части строки и удалите пробелы перед этим.


Вот небольшое упорядочение ответа Денниса Уильямсона.

awk -v word=alpha '$2==word { for (f=2; f<=NF; ++f) printf("%s%s", $f, (f==NF?ORS:OFS)) }'

Как и ответ Денниса, он выводит поля $2 , $3 ,…, $NF (без учета $1) с разделением по умолчанию.  Деннис использовал приближение $3 ,…, $NF (но не $2) с разделителем полей вывода по умолчанию.  Я выбрал следующий метод $2 , $3 ,…, $(NF-1) (но не $NF) с OFS. И, так как $NF следует выходной разделитель записей (ПРС), мы можем ?: оператор без нулевых терминов, и устранить окончательный printf("\n")

1
 % echo /var/sysconfig/network/my_functions  alpha beta gama | \
      awk -v word=alpha \
             '$2 == word { $1=""; print $0 }'
1

Я думаю, что в awk нет другого способа, кроме как удалить первое поле вручную. (Есть и другие способы, если вы хотите нормализовать пространство между полями.)

awk '$2 == word {match($0, "("FS")+"); print substr($0, RSTART+RLENGTH);}'
-1

Каждый всегда делает это сложнее, чем есть

$ echo /var/sysconfig/network/my_functions alpha beta gama |
awk -v word=alpha '$2==word{print substr($0,index($0,$2))}'
alpha beta gama
-1

Используйте это, если вы хотите изменить разделитель. Мой разделитель "|":

awk -F '|' '{d = ""; for (f=2; f<=NF; ++f) {printf("%s%s", d, $f); d = OFS}; printf("\n") }'

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .