У меня есть файл со многими строками в каждой строке есть много столбцов (полей), разделенных пробелом "" количество столбцов в каждой строке различно Я хочу удалить первые два столбца как?
Вы можете сделать это с помощью cut
:
cut -d " " -f 3- input_filename > output_filename
Объяснение:
cut
: вызвать команду cut-d " "
: в качестве разделителя используйте единое пространство (cut
использует TAB по умолчанию)-f
: укажите поля для сохранения3-
: все поля, начинающиеся с поля 3input_filename
: используйте этот файл как вход> output_filename
: напишите вывод в этот файл.В качестве альтернативы вы можете сделать это с помощью awk
:
awk '{$1=""; $2=""; sub(" ", " "); print}' input_filename > output_filename
Объяснение:
awk
: вызывать команду awk$1=""; $2="";
: установите поле 1 и 2 в пустую строкуsub(...);
: очистить выходные поля, потому что поля 1 и 2 все равно будут разделены символом ""print
: напечатать измененную строкуinput_filename > output_filename
: то же, что и выше.cut
использует табуляцию в качестве разделителя. Смотрите обновленный ответ - только что проверил и все работает. при прочих равных я бы порекомендовал использовать cut
over awk
.
Вот один из способов сделать это с Awk, который относительно легко понять:
awk '{print substr($0, index($0, $3))}'
Это простая команда awk без шаблона, поэтому действие внутри {}
выполняется для каждой строки ввода.
Действие состоит в том, чтобы просто напечатать подстроку, начиная с позиции третьего поля.
$0
: вся строка ввода$3
: 3-е полеindex(in, find)
: возвращает позицию find
в строке in
substr(string, start)
: вернуть подстроку, начинающуюся с индекса start
Если вы хотите использовать другой разделитель, например запятую, вы можете указать его с опцией -F:
awk -F"," '{print substr($0, index($0, $3))}'
Вы также можете использовать это в подмножестве входных строк, указав шаблон перед действием в {}
. Только строки, соответствующие шаблону, будут выполняться.
awk 'pattern{print substr($0, index($0, $3))}'
Где шаблон может быть таким, как:
/abcdef/
: использовать регулярное выражение, по умолчанию работает по $0.$1 ~ /abcdef/
: работайте в определенном поле.$1 == blabla
: используйте сравнение строкNR > 1
: использовать запись/номер строкиNF > 0
: использовать поле/номер столбцаСпасибо за сообщение вопроса. Я также хотел бы добавить script, который помог мне.
awk '{ $1=""; print $0 }' file
awk '{$1=$2="";$0=$0;$1=$1}1'
Ввод
a b c d
Выход
c d
$0=$0;$1=$1
для исчезновения пробелов
Довольно просто сделать это только с оболочкой
while read A B C; do
echo "$C"
done < oldfile >newfile
read -r
вместо read
.
read -r
сохранит обратную косую черту. read
не буду. Например: echo "foo ba\r"
выдаст вывод foo ba\r
. Тем не менее, echo "foo ba\r" | (while read first_column second_column; do echo "$second_column"; done)
будет выводить только bar
в качестве вывода (с удаленной обратной косой чертой. Добавление флага -r
приводит к правильному выводу ba\r
Вы можете использовать sed
:
sed 's/^[^ ][^ ]* [^ ][^ ]* //'
Это ищет строки, начинающиеся с одного или более не-пробелов, пробела, другого набора из одного или нескольких незабитых и еще одного пустого и удаляет сопоставленный материал, например первые два поля. [^ ][^ ]*
немного короче эквивалентной, но более явной нотации [^ ]\{1,\}
, а вторая может столкнуться с проблемами с GNU sed
(хотя, если вы используете --posix
в качестве опции, даже GNU sed
не может нафиг это). OTOH, если класс символов, который должен быть повторен, был более сложным, числовая нотация выигрывает для краткости. Его легко расширить, чтобы обрабатывать "пустую или табуляцию" как разделитель, или "множественные пробелы" или "множественные пробелы или вкладки". Он также может быть изменен для обработки необязательных заготовок (или вкладок) перед первым полем и т.д.
Для awk
и cut
см. Sampson-Chen ответ. Существуют и другие способы записи awk
script, но они не намного лучше, чем ответ. Обратите внимание, что вам может потребоваться явно задать разделитель полей (-F" "
) в awk
, если вы не хотите, чтобы вкладки обрабатывались как разделители или у вас могло быть несколько пробелов между полями. Стандарт POSIX cut
не поддерживает множественные разделители между полями; GNU cut
имеет полезную, но нестандартную опцию -i
, позволяющую использовать несколько разделителей между полями.
Вы также можете сделать это в чистой оболочке:
while read junk1 junk2 residue
do echo "$residue"
done < in-file > out-file
residue
может содержать обратную косую черту, приведенное выше чтение будет интерпретировать его, а не воспроизводить его в выходных данных. Всегда используйте, while IFS= read -r ...
bash
интерпретирует содержимое с простым read
, то bash
работает (снова). Команда чтения в оригинальных оболочках не делала такой ерунды; Я не верю, что это требуется оболочкой POSIX. Меня раздражало бы, что bash
делает то, что вы говорите, - у меня уже есть отношения любовь / ненависть с программой, поскольку она делает много вещей хорошо, но есть некоторые вещи, которые она делает плохо, и изменение устаревшего поведения является одним из худших, и требование опции для включения старого стандартного поведения ... очень раздражает. Кажется, ты прав; bash
завален!
Perl:
perl -lane 'print join(' ',@F[2..$#F])' File
AWK:
awk '{$1=$2=""}1' File
Это может сработать для вас (GNU sed):
sed -r 's/^([^ ]+ ){2}//' file
или для столбцов, разделенных одним или несколькими пробелами:
sed -r 's/^(\S+\s+){2}//' file
Используя awk и, основываясь на некоторых из приведенных ниже опций, использование цикла for делает немного более гибким; иногда я могу удалить первые 9 столбцов (например, я делаю "ls -lrt" ), поэтому я меняю 2 на 9 и что он:
awk '{ for(i=0;i++<2;){$i=""}; print $0 }' your_file.txt
Используйте kscript
kscript 'lines.split().select(-1,-2).print()' file