- Печать всего, кроме первого поля с awk
- Объяснение
- Вариант 1
- Вариант 2
- Вариант 3
- Распечатать все столбцы, кроме первого, используя AWK
- 6 ответов
- Пояснение:
- Использование awk для печати всех столбцов от n-го до последнего
- 24 ответов
- Вариант 4 (рекомендуется)
- Вывести все столбцы, кроме первых трех
- 19 ответов
- Опция 1
- Вариант 2
- Вариант 3
- Вариант 4
- Вариант 5
Печать всего, кроме первого поля с awk
У меня есть файл, который выглядит так:
И я бы хотел инвертировать заказ, сначала распечатать все, кроме $1, а затем $1:
Как я могу сделать трюк “все, кроме поля 1”?
Присвоение $1 работает, но оно оставляет ведущее пространство: awk ‘
Вы также можете найти количество столбцов в NF и использовать это в цикле.
$1=»» оставляет пробел, как упоминал Бен Джексон, поэтому используйте цикл for :
Итак, если ваша строка была “одна две три”, вывод будет:
Если вы хотите получить результат в одной строке, вы можете сделать следующее:
Это даст вам: “два три”
Используйте команду cut с опцией —complement :
Возможно, самый сжатый способ:
$(NF+1)=$1 : Генератор “нового” последнего поля.
$1=»» : установите исходное первое поле в значение null
sub(FS,»») : после первых двух действий <$(NF+1)=$1;$1="">избавиться от первого разделителя полей, используя sub. Окончательный вывод неявный.
Удалите первое поле и разделитель и напечатайте результат ( 7 – это ненулевое значение, поэтому печать $0).
Установка первого поля в «» оставляет единственную копию OFS в начале $0 . Предполагая, что OFS – это только один символ (по умолчанию это одно пространство), мы можем удалить его с помощью substr($0, 2) . Затем добавим сохраненную копию $1 .
Если вы открыты для решения Perl…
– простое решение с разделителем ввода/вывода одного пространства, которое производит:
Этот следующий немного сложнее
и предполагает, что разделитель ввода/вывода имеет два пробела:
Эти параметры командной строки используются:
-n цикл вокруг каждой строки входного файла, автоматически не печатайте каждую строку
-l удаляет новые строки перед обработкой и добавляет их обратно
-a режим автосброса – разделение входных строк на массив @F. По умолчанию разделение на пробелы
-F модификатор autosplit, в этом примере разбивается на ” (два пробела)
-e выполните следующий код perl
@F – это массив слов в каждой строке, индексированный начиная с 0
$#F – количество слов в @F
@F[1..$#F] – это срез массива элемента 1 через последний элемент
@F[1..$#F,0] – это срез массива элемента 1 через последний элемент плюс элемент 0
Разделитель полей в gawk (по крайней мере) может быть строкой, а также символом (он также может быть регулярным выражением). Если ваши данные согласованы, то это будет работать:
Это два пробела между двойными кавычками.
Переместите все записи в следующую и установите последнее как первое:
Объяснение
- a=$1 сохранить первое значение во временную переменную.
- for (i=2; i сохранить значение N-го поля в поле (N-1) th.
- $NF=a сохраните первое значение ( $1 ) в последнем поле.
- <>1 истинное условие сделать awk выполнить действие по умолчанию:
.
Таким образом, если у вас есть другой разделитель полей, результат тоже хорош:
Первый удар в нем, похоже, работает для вашего конкретного случая.
Вариант 1
Существует решение, которое работает с некоторыми версиями awk:
Однако это может закончиться с более старыми версиями awk.
Вариант 2
Обратите внимание, что то, что нужно удалить, – это OFS, а не FS. Строка пересчитывается, когда поле $1 присваивается. Это изменяет все прогоны FS на один OFS.
Но даже этот параметр по-прежнему терпит неудачу с несколькими разделителями, что ясно видно из-за изменения OFS:
Эта строка выводит:
Это показывает, что прогоны FS меняются на один OFS.
Единственный способ избежать этого – избежать перерасчета поля.
Одна функция, которая может избежать повторного вычисления, – это sub.
Первое поле можно было бы захватить, затем удалить из $0 с помощью sub, а затем перепечатать.
Вариант 3
Даже если мы изменим FS, OFS и/или добавим больше разделителей, он работает.
Если входной файл изменен на:
И команда изменится на:
Выход будет (сохраняется сохранение разделителей):
Команда может быть расширена до нескольких полей, но только с современными awks и с активным параметром -re-interval. Эта команда в исходном файле:
Источник
Распечатать все столбцы, кроме первого, используя AWK
У меня есть файл, который содержит список файлов. Файл выглядит так
Я хочу вырезать первые два столбца и печатать только имена файлов по пути к каталогу. Этот список является динамическим. Имя файла содержит пробелы между ними. Поэтому я не могу использовать пробел в качестве разделителя. Как получить это используя команду AWK ?
Вывод должен быть таким
6 ответов
печатать только имена файлов с указанием пути к каталогу
Подход awk :
Чтобы извлечь только базовое имя из файла:
Можете ли вы попробовать это один раз:
Иначе, если вы хотите удалить 2 столбца, это будет:
Это даст следующий вывод:
Это сделает именно то, что вы хотите для вашего примера:
Пояснение:
Он соответствует вашему пути (включая пробелы, если таковые были), а затем заменяет всю строку этим совпадением. Легкий гороховый лимонный отжим 🙂
Это ноль или более непустых символов, за которыми следует косая черта, за которой следует остальная часть строки.
Это не будет соответствовать ни одной строке, которая не имеет косой черты
Здесь sed используется для удаления первого пробела выходной строки.
Вот портативное решение для оболочки POSIX:
Это перебирает каждую строку заданного входного файла (ов) (или другого стандартного ввода) и печатает строку без первых двух пробелов или текста, который существует перед ними. Это не жадный.
В отличие от некоторых других ответов здесь, это сохранит интервал (если есть) в остальной части строки.
Если вы хотите это как однострочник:
Это не удастся, если имя самого верхнего каталога начинается с пробела. Чтобы обойти это, вам нужно удалить первые десять символов (которые, я полагаю, являются статическими):
Как однострочник, в bash это можно упростить, используя подстроки:
Источник
Использование awk для печати всех столбцов от n-го до последнего
эта строка работала, пока у меня не было пробелов во втором поле.
есть ли способ заставить awk печатать все в $2 или больше? ($3, $4.. пока у нас не закончатся колонки?)
полагаю, я должен добавить, что я делаю это в среде Windows с Cygwin.
24 ответов
напечатает все, кроме самого первого столбца:
напечатает все, кроме двух первых столбцов:
есть дубликат вопроса с проще ответить использование cut:
-d задает разделитель (пробел), -f задает список столбцов (все начиная со 2-ой)
вы можете использовать for-loop для циклической печати полей $2 через $NF (встроенная переменная, представляющая количество полей в строке).
изменить: Поскольку «печать» добавляет новую строку, вы захотите буферизировать результаты:
в качестве альтернативы используйте printf:
мой ответ основан на один из VeeArr, но я заметил, что он начался с пробела, прежде чем печатать второй столбец (и все остальное). Поскольку у меня есть только 1 репутационный пункт, я не могу прокомментировать его, поэтому здесь он идет как новый ответ:
начните с » out » в качестве второго столбца, а затем добавьте все остальные столбцы (если они существуют). Это хорошо, пока есть вторая колонка.
Я лично пробовал все ответы, упомянутые выше, но большинство из них были немного сложными или просто неправильными. Самый простой способ сделать это с моей точки зрения:
где-F «» определяет разделитель для awk для использования. В моем случае это пробел, который также является разделителем по умолчанию для awk. Это означает, что-F» » можно игнорировать.
где NF определяет общее количество полей / столбцов. Поэтому цикл начнется от 4-го поля до последнего поля / столбца.
где $N получает значение N-го поля. Поэтому print $i будет печатать текущее поле / столбец на основе подсчета циклов.
большинство решений с awk оставляют пространство. Варианты здесь избегают этой проблемы.
простое решение для вырезания (работает только с одиночными разделителями):
принудительное повторное вычисление awk иногда удаляет добавленное ведущее пространство (OFS), удаляя первые поля (работает с некоторыми версиями awk):
печать каждого поля в формате printf будет дайте больше контроля:
однако все предыдущие ответы меняют все повторяющиеся FS между полями на OFS. Давайте построим пару вариантов, которые этого не делают.
Вариант 4 (рекомендуется)
цикл с sub для удаления полей и разделителей спереди.
И используя значение FS вместо пространства (которое может быть изменено).
Является более портативным и не вызывает изменения FS в OFS: Примечание: на ^[FS]* принять вход с ведущими пробелами.
вполне возможно построить решение, которое не добавляет дополнительные (ведущие или конечные) пробелы и сохраняет существующие пробелы с помощью функции gensub от GNU awk, как это:
он также может использоваться для замены группы полей с учетом count n :
конечно, в таком случае OFS используется для разделения обеих частей линии и трейлинга белое пространство полей все еще печатается.
Примечание: [FS]* используется для разрешения ведущих пробелов во входной строке.
это меня так раздражало, что я сел и написал cut -как синтаксический анализатор спецификации поля, протестированный с GNU Awk 3.1.7.
сначала создайте новый скрипт библиотеки Awk под названием pfcut , например,
затем вставьте в скрипт ниже и сохраните. После этого, вот как выглядит использование:
чтобы избежать ввода всего этого, я думаю, лучшее, что можно сделать (см. В противном случае автоматически загружать функцию пользователя при запуске с awk? — В Unix И Linux Стек Обмен) — добавить псевдоним
Источник
Вывести все столбцы, кроме первых трех
19 ответов
Решение, которое не добавляет дополнительных начальных или конечных пробелов:
Sudo_O предлагает элегантное улучшение с использованием тернарного оператора NF?ORS:OFS
EdMorton предлагает решение, сохраняющее исходные пробелы между полями:
BinaryZebra также предлагает два отличных решения:
(эти решения даже сохраняют конечные пробелы из исходной строки)
Решение, данное larsr в комментариях, почти правильно:
Это фиксированная и параметризованная версия решения larsr:
Все остальные ответы до сентября 2013 года хороши, но добавляют лишние пробелы:
Или если вы настаиваете на awk и $ 13 — последнее поле
Другой способ избежать использования оператора печати:
В awk, когда условие истинно, печать является действием по умолчанию.
Не могу поверить, что никто не предлагал простую оболочку:
Варианты с 1 по 3 имеют проблемы с несколькими пробелами (но они просты). Это причина разработки вариантов 4 и 5, которые без проблем обрабатывают несколько пробелов. Конечно, если варианты 4 или 5 используются с n=0 , оба сохранят любые начальные пробелы, поскольку n=0 означает отсутствие разделения.
Опция 1
Простое решение для резки (работает с одиночными разделителями):
Вариант 2
Принудительное повторное вычисление awk иногда решает проблему (работает с некоторыми версиями awk) с добавленными ведущими пробелами:
Вариант 3
Печать каждого поля, сформированного с помощью printf , даст больше контроля:
Однако все предыдущие ответы меняют все FS между полями на OFS. Давайте создадим для этого пару решений.
Вариант 4
Цикл с подпрограммой для удаления полей и разделителей более переносим и не вызывает изменения FS на OFS:
ПРИМЕЧАНИЕ. «^ [» FS «] *» означает ввод с пробелами в начале.
Вариант 5
Вполне возможно построить решение, которое не добавит лишних начальных или конечных пробелов и сохранит существующие пробелы, используя функцию gensub из GNU awk, как это:
Его также можно использовать для замены списка полей с учетом счетчика n :
Конечно, в таком случае OFS используется для разделения обеих частей строки, а конечные пробелы полей по-прежнему печатаются.
Примечание 1: [«FS»]* используется для разрешения начальных пробелов в строке ввода.
Cut имеет флаг —complement, который упрощает (и ускоряет) удаление столбцов. Результирующий синтаксис аналогичен тому, что вы хотите сделать, — это упрощает чтение / понимание решения. Дополнение также работает в случае, когда вы хотите удалить несмежные столбцы.
Решение Perl, которое не добавляет начальные или конечные пробелы:
Массив perl @F autosplit начинается с индекса 0 , а поля awk начинаются с $1
Решение Perl для данных, разделенных запятыми:
python -c «import sys;[sys.stdout.write(‘ ‘.join(line.split()[3:]) + ‘\n’) for line in sys.stdin]»
Для меня наиболее компактным и совместимым решением запроса является
И если вам нужно обработать больше строк, например файл foo.txt , не забудьте сбросить i на 0:
Спасибо вашему форуму.
Поскольку меня раздражал первый, получивший большое количество голосов, но неправильный ответ, я нашел достаточно, чтобы написать там ответ, а здесь неправильные ответы отмечены как таковые, вот моя доля. Мне не нравятся предлагаемые решения, так как я не вижу причин давать такой сложный ответ.
У меня есть журнал, в котором после 5 долларов с IP-адресом может быть больше текста или нет текста. Мне нужно все, от IP-адреса до конца строки, если что-то стоит после 5 долларов. В моем случае это действительно с awk-программой, а не с одной строкой awk, поэтому awk должен решить проблему. Когда я пытаюсь удалить первые 4 поля, используя старый красивый и получивший наибольшее количество голосов, но совершенно неправильный ответ:
Он выдает неправильный и бесполезный ответ (я добавил [] для демонстрации):
Вместо этого, если столбцы имеют фиксированную ширину до тех пор, пока не потребуется точка отсечения и awk, правильный и довольно простой ответ:
Который дает желаемый результат:
Я нашел эту возможность, может быть, она тоже может быть полезна .
Примечание. 1. Для табличных данных и столбцов от 1 до 14 долларов
Например: Если у вас есть file1 , содержащий: car.is.nice.equal.bmw
Выполнить: cut -d . -f1,3 file1 напечатает car.is.nice
Правильный способ сделать это — использовать интервал RE, потому что он позволяет вам просто указать, сколько полей нужно пропустить, и сохраняет интервалы между полями для остальных полей.
Например пропустить первые 3 поля, не влияя на интервал между оставшимися полями, учитывая формат ввода, который мы, кажется, обсуждаем в этом вопросе, просто:
Если вы хотите разместить ведущие пробелы и непустые пробелы, но опять же с FS по умолчанию, тогда это:
Если у вас есть FS, который является RE, который вы не можете отрицать в наборе символов, вы можете сначала преобразовать его в один символ (RS идеально подходит, если это один символ, поскольку RS НЕ МОЖЕТ появляться в поле, в противном случае рассмотрите SUBSEP), затем примените замену интервала RE, затем преобразуйте в OFS. например если цепочки «.» разделяют поля:
Очевидно, что если OFS — это один символ и он не может отображаться в полях ввода, вы можете уменьшить его до:
Тогда у вас будет та же проблема, что и со всеми решениями на основе цикла, которые переназначают поля — FS преобразуются в OFS. Если это проблема, вам нужно изучить функцию patsplit () GNU awks.
Практически все ответы в настоящее время добавляют либо ведущие пробелы, либо конечные пробелы, либо некоторые другие проблемы с разделителями. Чтобы выбрать из четвертого поля, где разделителем является пробел, а разделителем вывода является одиночный пробел, используя awk , будет:
Чтобы параметризовать начальное поле, вы можете сделать:
Источник