sed -n '/search?q=/{s/.*search?q=//;p;}' infile > outfile
Объяснение:
/ search? Q = /
создает следующий набор команд (в фигурные скобки) применяются только к строкам, содержащим это регулярное выражение.
s /.* search? Q = //
заменяет первую часть второй (пустой).
Затем p
печатает строку.
Флаг -n
подавляет печать строки по умолчанию.
Фактически, вы можете упростить это следующим образом:
sed -n '/.*search?q=/{s///;p;}' infile > outfile
Потому что, когда рисунок, подаваемый в команду s /
, остается пустым, последний использованный рисунок используется снова.
РЕДАКТИРОВАТЬ: Спасибо RobertL за указание на упрощение в комментариях:
sed -n 's/.*search?q=//p' infile > outfile
Здесь используется флаг p
для команды s
, которая выводит строку только в том случае, если замена была произведена.
Это, кажется, делает это. Будучи простой одной строкой awk
, он должен довольно быстро работать с файлом строк размером 1,2 млн. Создав фиктивный файл из 1,3 млн строк на основе вашего образца, я увидел, что он был завершен за 24 секунды на базовой виртуальной машине CentOS 7 с 4 ГБ памяти и GNU Awk 4.0.2.
Чтобы получить точные ответы от StackExchange, вы можете опубликовать свой образец ввода на pastebin вместе с образцом вывода.
$ awk '{printf "%s %-6s%-81s%-12s%-12s%s\n",$1,$2,gensub(/[0-9.-]* +[0-9.-]* +[0-9]$/,"","g",substr($0,10)),$(NF-2),$(NF-1),$NF}' inp | head
AD AD100 Canillo 42.5833 1.6667 6
AD AD200 Encamp 42.5333 1.6333 6
AD AD300 Ordino 42.6 1.55 6
AD AD400 La Massana 42.5667 1.4833 6
AD AD500 Andorra la Vella 42.5 1.5 6
AD AD600 Sant Julià de Lòria 42.4667 1.5 6
AD AD700 Escaldes-Engordany 42.5 1.5667 6
AR 3636 POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S)) Salta A -23.4933 -61.9267 3
AR 4123 LAS SALADAS Salta A -25.7833 -64.5 4
AR 4126 BARADERO Salta A -26.0833 -65.263 3
$
Я смог выполнить то, что, как мне кажется, вы хотите, с помощью следующего скрипта, хотя я не уверен, насколько хорошо он будет работать с более чем 1 млн строк.
#!/usr/local/bin/bash
tmp_dir="$(mktemp -d -t 'text.XXXXX' || mktemp -d 2>/dev/null)"
input=./input
output=./output
tmp_input1=${tmp_dir}/temp_input1.txt
tmp_input2=${tmp_dir}/temp_input2.txt
col1="${tmp_dir}/col1.txt"
col2="${tmp_dir}/col2.txt"
col3="${tmp_dir}/col3.txt"
col4="${tmp_dir}/col4.txt"
col5="${tmp_dir}/col5.txt"
col6="${tmp_dir}/col6.txt"
tr -s ' ' <"$input" > "$tmp_input1"
awk '{print $1}' "$tmp_input1" > "$col1"
awk '!($1="")' "$tmp_input1" > "$tmp_input2"
awk '{print $1}' "$tmp_input2" > "$col2"
awk '!($1="")' "$tmp_input2" > "$tmp_input1"
awk '{print $NF}' "$tmp_input1" > "$col6"
awk '!($NF="")' "$tmp_input1" > "$tmp_input2"
awk '{print $NF}' "$tmp_input2" > "$col5"
awk '!($NF="")' "$tmp_input2" > "$tmp_input1"
awk '{print $NF}' "$tmp_input1" > "$col4"
awk '!($NF="")' "$tmp_input1" > "$tmp_input2"
cat "$tmp_input2" > "$col3"
paste -d'\t' "$col1" "$col2" "$col3" "$col4" "$col5" "$col6" | column -s$'\t' -t > "$output"
rm -r "$tmp_dir"
Это создает набор файлов tmp (по одному для каждого столбца и два для модификации исходного файла )и обрабатывает ваш исходный ввод, удаляя по одному столбцу за раз, пока не останется со столбцом 3. Затем он вставляет все файлы tmp разделены вкладкой и используют column
для форматирования вывода по вашему желанию.
С вашими данными:
$./script.sh
$ cat output
AD AD100 Canillo 42.5833 1.6667 6
AD AD200 Encamp 42.5333 1.6333 6
AD AD300 Ordino 42.6 1.55 6
AD AD400 La Massana 42.5667 1.4833 6
AD AD500 Andorra la Vella 42.5 1.5 6
AD AD600 Sant Julià de Lòria 42.4667 1.5 6
AD AD700 Escaldes-Engordany 42.5 1.5667 6
AR 3636 POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S)) Salta A -23.4933 -61.9267 3
AR 4123 LAS SALADAS Salta A -25.7833 -64.5 4
AR 4126 BARADERO Salta A -26.0833 -65.263 3
AR 4126 EL CUIBAL Salta A -26.0833 -65.263 3
AR 4126 LA ASUNCION Salta A -26.0833 -65.263 3
AR 4126 MIRAFLORES (TALA, DPTO. CANDELARIA) Salta A -26.0833 -65.263 3
AR 4141 TOLOMBON Salta A -26.2 -65.9167 4
AR 4141 QUISCA GRANDE Salta A -26.4367 -65.97 3
AR 4141 LA CIENEGUITA Salta A -26.4367 -65.97 3
AR 4141 MACHO RASTROJO Salta A -26.4367 -65.97 3
AR 4190 ROSARIO DE LA FRONTERA Salta A -25.8 -64.9667 4
AR 4190 OVANDO Salta A -25.8 -65.1 4
AR 4190 SAN ESTEBAN Salta A -25.8 -65.0333 3
AR 4190 LA BANDA (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA) Salta A -25.8 -65.0333 3
AR 4190 LA MATILDE Salta A -25.8 -65.0333 3
AR 4190 LAS PIEDRITAS Salta A -25.8 -65.0333 3
AR 4190 LOS POCITOS Salta A -25.8 -65.0333 3
AR 4190 OJO DE AGUA (ROSARIO DE LA FRONTERA, DPTO. R.DE LA FRONTERA) Salta A -25.8 -65.0333 3
AR 4190 POTRERILLO (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA) Salta A -25.8 -65.0333 3