Форум программистов, компьютерный форум, киберфорум
Shell, Bash
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
2 / 2 / 0
Регистрация: 16.10.2020
Сообщений: 2

awk и удаление лишних строк

16.10.2020, 12:25. Показов 2398. Ответов 4

Студворк — интернет-сервис помощи студентам
Здравствуйте!

Столкнулся с проблемой выборки текста средствами awk в файле вида:
Code
1
2
3
4
5
6
7
8
9
TEXT
TEXT XYZ
XY TEXTTE
XY TEXT
XY TEXTTEXT
XY-TEXTTEXT TEXT XY
XY-TEXTTEXT TEXT XY (TEXT)
XY-TEXTTEXT TEXT XY (TEXTTEXT)
XY-TEXTTEXT TEXT XY (TEXTTE)
Хотел получить следующий вывод по самому короткому совпадению:
Code
1
2
3
4
5
TEXT
XY TEXTTE
XY TEXT
XY TEXTTEXT
XY-TEXTTEXT TEXT XY
Родилась следующая конструкция:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/awk -f
$0 !~ /((\r\n|\n|\r)$)|(^(\r\n|\n|\r))|^\s*$/{
  while (NR <= 200) {
    z1=$0; y1=$1; y10=$2; y100=$3; x1=length($0); w1=NF;
    getline
    z2=$0; y2=$1; y20=$2; y200=$3; x2=length($0); w2=NF;
    #во имя отладки ты и родилась: print "W="w1","w2", X="x1","x2", Y="y1","y2", Y2="y10","y20", Z="z1","z2;
    if      (z1 ""!= z2 ""&&(y1 ""== y2 ""&& (y10 != ""|| y20 != "")) && x2 < x1) {print z2}
    else if (z1 ""!= z2 ""&&(y1 ""== y2 ""&& (y10 != ""|| y20 != "")) && x1 < x2) {print z1}
    else {printf z1"\n"z2"\n"};
    break
  }
}
Пробежавшись по форуму натолкнулся на следующую конструкцию: awk '!D[$1]++' filename , что меня очень и очень заинтересовало. Прекрасно понимаю, что оно делает, но пока не дошёл как приспособиться к этой конструкции, потому как она делает выборку по первой подстроке.

Больше готового решения жажду наводки. Банальности вроде "прочти руководства тонну" и ссылка: принимаются ;-).

Всем добра.

P.S. задачу свою в любом случае решил башем, хочется средствами awk. Заранее спасибо.
P.P.S. ЧЯДНТ?
2
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.10.2020, 12:25
Ответы с готовыми решениями:

Сцепка текста в ячейках, если совпадают значения в столбце А, удаление повторов имен, удаление лишних строк
Добрый день, подскажите, как решить задачу: Есть список организаций с контактами. Одна организация может быть представлена разным...

Сортировка и удаление лишних строк
Помогите с кодом сортировки. В общем в текстовую строку пишите номер магазина, все записи с этим номером показываются на листе, а остальные...

Удаление лишних строк в reg-файле
Приветствую всех ! К примеру имеется дамп ветки реестра HKLM\SYSTEM\CurrentControlSet\services И мне нужно из этого Windows...

4
49 / 49 / 14
Регистрация: 21.03.2011
Сообщений: 113
16.10.2020, 12:42
Исходя из условия, должно помочь

Bash
1
awk '(length($1) > 2 && !D[$1]++) || (length($1) <= 2 && !D[$1,$2]++)' filename
1
Эксперт NIX
 Аватар для nezabudka
3334 / 752 / 252
Регистрация: 28.06.2015
Сообщений: 1,552
Записей в блоге: 16
16.10.2020, 17:18
Лучший ответ Сообщение было отмечено apeshand как решение

Решение

Попробовала изменить порядок строк во входном файле и усложнить ради спортивного интереса:
cat file:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
TEXT XYZ
TEXT
XY TEXT
XY TEXTTE
XY-TEXTTEXT TEXT XY
XY-TEXTTEXT TEXT XY (TEXT)
XY TEXTTEXT
XY-TEXTTEXT TEXT XY (TEXTTEXT)
XY-TEXTTEXT TEXT XY (TEXTTE)
XY-TEXTTEXT TEXT X
XY-TEXTTEXT TEXT XYZ
TEX
cat awk.sh:
Bash
1
2
3
4
5
6
#!/bin/bash
awk '
NR==FNR {A[$0]; next}
        {a=$0; NF-=1; if(!($0 in A)) D[a]}
END     {for(i in D) print i}
' file{,}
Bash
1
2
3
4
5
6
7
8
9
./awk.sh
XY TEXTTE
XY-TEXTTEXT TEXT XY
TEXT
TEX
XY-TEXTTEXT TEXT XYZ
XY TEXTTEXT
XY TEXT
XY-TEXTTEXT TEXT X
Добавила сортировку:
Bash
1
2
3
4
5
6
awk '
BEGIN   {PROCINFO["sorted_in"]="@ind_str_asc"}
NR==FNR {A[$0]; next}
        {a=$0; NF-=1; if(!($0 in A)) D[a]}
END     {for(i in D) print i}
' file{,}
Bash
1
2
3
4
5
6
7
8
9
./awk.sh
TEX
TEXT
XY TEXT
XY TEXTTE
XY TEXTTEXT
XY-TEXTTEXT TEXT X
XY-TEXTTEXT TEXT XY
XY-TEXTTEXT TEXT XYZ
2
2 / 2 / 0
Регистрация: 16.10.2020
Сообщений: 2
16.10.2020, 18:00  [ТС]
Спасибо за Ваш ответ, nezabudka, и ответ sonar200.

Возник ряд вопросов касательно кода с сортировкой:
BEGIN {PROCINFO["sorted_in"]="@ind_str_asc"}
- вот эта магия совершенно непонятна. Символ @ в awk встречал разве что... касательно выборок по паттерну вида @/foo/ - жёсткий поиск, насколько помню в отличии от /foo/ - нахождения в строке.
NR==FNR {A[$0]; next}
- как понимаю тут формируется одномерный массив содержащий в первом столбце всю строку $0 пока NR - номер строки, не сравняется с общим количеством строк FNR на входе. Какой-то странный аналог while без while, как мне видется.
{a=$0; NF-=1; if(!($0 in A)) D[a]}
- тут объявляется переменная a, равная всей строке $0; теперь непонятно - зачем мы отнимаем у строки единицу в значении кол-ва полей?; последняя конструкция этой строки чуточку яснее "если строка $0 не в массиве A, то" что - что это значит? Спрашиваю, потому как подобная конструкция была в моём вопросе, значащая дубль. То есть выходит, что это создаёт дубль строки?
END {for(i in D) print i}
- опять непонятно. "для каждой i в D(БОЖЕЧКИ! АБЯСНИТЕ!) печатай i"
file{,}
- что значат фигурные скобки с запятой применительно к названию?

Как говорил ранее - можете направить на чтение документации, если в доке есть примеры - спасёт время и нервы, если нет - пожалуйста объясните, хотя бы своими словами.

P.S. в итоге из 5 строчек у меня счёт на понимание меньше единицы.
0
Эксперт NIX
 Аватар для nezabudka
3334 / 752 / 252
Регистрация: 28.06.2015
Сообщений: 1,552
Записей в блоге: 16
16.10.2020, 20:14
apeshand, Судя по уровню ваших вопросов, рискну объяснить своими словами, думаю это будет полезней, но все равно вам стоит хотя бы по диагонали пролистать ман страничку man awk.
PROCINFO это внутренняя переменная - массив, через который можно влиять на работу процессора awk в том числе и сортировку. Попробуйте изменить значение с "@ind_str_asc" на "@ind_str_desc" и получите обратную сортировку по убывающей. Заметно невооруженным глазом, что значение состоит из трех объектов, читаю с переводом на русский по порядку @индекс_строка_поВозростанию, следующая - @индекс_строка_поУбыванию. Индекс - в данном случае имеется ввиду ключ
NR==FNR {A[$0]; next} Предполагает что процессор работает с несколькими файлами и массив из всех строк первого файла создается в переменной А. Я написала один и тот же файл в программе два раза, применяя "Расскрытие скобок", первый раз читая файл процессор создает массив, а второй производит обработку с записью в другой массив D. Расскрытие скобок или Brace Expantion хорошо наблюдать через команду echo:
Bash
1
2
echo 1{a,b,c}
1a 1b 1c
или как в нашем случае:
Bash
1
2
echo file{,}
file file
Получим как видите 2 файла. Их можно в программе так и указать безо всяких раскрытий скобок. Кстати, два файла нужны в моем случае из за того, что порядок следования строк перемешан и зачастую более короткое значение идет после длинного и необходимо к моменту обработки иметь полную базу всех вариантов.
Что касается вот этой конструкции {a=$0; NF-=1; if(!($0 in A)) D[a]}, давайте немного изменим программу и возьмем в качестве аргумента ваш первоначальный пример входного файла:
Bash
1
2
3
4
5
6
7
awk '
NF == 1 {a=$0; NF=0; if (!($0 in D)) D[a]}
NF == 2 {a=$0; NF=1; if (!($0 in D)) D[a]}
NF == 3 {a=$0; NF=2; if (!($0 in D)) D[a]}
NF == 4 {a=$0; NF=3; if (!($0 in D)) D[a]}
END     {for(i in D) print i}
' file
Смотрите что получается, я начну объяснять со второй строчки программы. В строке тело выполняется если строка состоит из двух слов (полей), переменная NF количество полей в строке. Мы присваиваем переменной a всю строку целиком, чтобы не потерять это значение, потому что следующая операция не обратима. Урезаем количество полей на единицу NF=1. Теперь у нас вся строка определенная в переменной $0 урезается на одно - последнее поле, и там ноходится только первое. Теперь проверяем есть ли совпадение в ключе массива D, если нет, добавляем в массив значение (0 по умолчанию) с ключем - первоначальной, не урезанной, полной строкой. Это дает нам возможность применить нежадный алгоритм - то есть по короткому совпадению.
Возвращаемся и видим что одна строчка в боевой программе является универсальной и заменяет множество возможных вариантов из учебной.
Как только скрипт обработает значения и создаст результирующий массив данных, можно прочитать его ключи в цикле и вывести на экран. То есть уже после того как файлы будут прочитаны. Аналог END {for(i in D) print i} на баше будет:
Bash
1
2
3
for i in ${!D[@]};
  do echo $i;
done
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.10.2020, 20:14
Помогаю со студенческими работами здесь

Удаление лишних строк - доделать макрос
Приветствую знатоков и прошу помочь доделать код. Есть текстовые данные, разбитые постранично. На каждой странице титульная часть из 2...

Удаление лишних строк таблицы, парсер PS
Здравствуйте! Имеется скрипт парсера некой веб - страницы, содержащую таблицу. Таблица извлечена из тега &lt;table&gt;: $uri =...

Программное удаление лишних строк таблицы DataGridView
Имеется программа. При считывании из файла таблица заполняется таким образом (рис.1). При нажатии на кнопку &quot;Рассчитать таблицу&quot;...

Упражнение 1.18 Удаление лишних пробелов, табуляций и строк
Упражнение 1.18. Напишите программу, которая будет в каждой вводимой строке заменять стоящие подряд символы пробелов и табуляций на один...

Удаление лишних пустых строк и пробелов на конце строки
open(FIL,&quot;azaz.txt&quot;); my @s =&lt;FIL&gt;; close FIL; for ($i=0; $i &lt;= 9; $i++) { if ( length( $s ) &gt; 1 ) { $s =~ s/^\s+//; print...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru