LinuxForum.Fans
Тема

Shell-процедуры

Автор: Gard 45 сообщений 15922 просмотров 🔒 закрыта
#120898

вот в этом посте http://linuxforum.ru/viewtopic.php?pid=135080#p135080 применён страшный код:

text
sed -rn '
                s/.*/\n&\n/
                :l
                s/\n(.)(.*)(.)\n/\3\n\2\n\1/
                t l            
                s/\n//g
                p'

его не я придумал, а прочитал о нём в info sed. вот по-русски: http://drbatty.ru/sed/ch07.html


Инверсия порядка символов в строке.

Этот скрипт меняет последовательность символов в строке на противоположную, например

[console]$ echo "ABCDEFGHJ" | ./reverseline.sed
JHGFEDCBA
[/console]

Пример 7.6.

text
#!/usr/bin/sed -rf

# если в строку нет 2х символов (иначе, длинна строки меньше двух), # то ничего не делаем /../! b

# Реверс строки

# сначала в начало и в конец строки добавляются символы \n. s/^.*$/\ &\ /

# Обмен первого и последнего символа местами, символы меняются # вместе с маркёрами \n, причём относительный порядок символа и маркёра # не меняется. Поэтому маркёры оказываются "внутри" - например: # \n F .* E \n --- до замены # E \n .* \n F --- после # Цикл продолжается пока внутри не останется 1 или 0 символов. tx :x s/(\n.)(.*)(.\n)/\3\2\1/ tx

# Удаление маркёров. s/\n//g

да, код слегка изменён, ибо идею я помнил, а читать свой-же перевод мне было лениво ;)

ЗЫЖ у меня тут ошибочка - я не сбросил флаг перехода (а в info sed всё правильно). только это не страшно - в первый раз переход выполняется ВСЕГДА. потому если у нас например менять нечего (реверс строки "Z"), то программа пытается осуществить реверс ДВА раза, хотя достаточно одного. но это не страшно. оба раза команда s НЕ выполняется. ;)

#120905

примечание к посту http://linuxforum.ru/viewtopic.php?pid=136055#p136055

text
sed -rn "/^$1:/s/([^:]*:){3}//;T;s/,/\n/gp" /etc/group | tee users.tmp

лихо закрученный однострок, неправда-ли? :P

text
sed -rn "
/^$1:/s/([^:]*:){3}//
T
s/,/\n/gp
" /etc/group | tee users.tmp

Здесь я пропарсил файл /etc/group. Тут мы видим мою любимую sed, но не всё так просто: я всегда заключаю sed-скрипт 'в одиночные кавычки', когда он внутри shell-скрипта. Кроме исключительных случаев. Тут как раз такой случай, это не просто shell-скрипт, а shell-функция, причём с параметром. Этот параметр называется $1 и имеет значение adm. При этом сам скрипт заключён в "двойные кавычки", что приводит к замене $1 на adm (это делает shell). Потому на самом деле sed получает такой скрипт:

text
sed -rn "
/^adm:/s/([^:]*:){3}//
T
s/,/\n/gp
" /etc/group | tee users.tmp

первая строчка /^adm:/s/([^:]*:){3}// имеет адресное выражение /^adm:/, и потому действует лишь на строки, которые начинаются на adm:, а именно на эту:
adm:x:4:root,adm,daemon
команда s/([^:]*:){3}// удаляет {три} последовательности (в скобках). Последовательности [^:]*:, что по-русски значит: любые символы кроме двоеточия в любом количестве, за которыми идёт двоеточие. Т.е. удаляется
adm:x:4:
И остаётся
root,adm,daemon
Это список пользователей, которые входят в группу adm, через запятую. Если мы нашли ненужную строчку, то командой T мы переходим к анализу следующей, нужная строчка обрабатывается далее - все запятые меняются на перевод строки, и у нас получается три строки:
root
adm
daemon

т.е. список нужных юзеров. Этот список выводится и на экран, и в файл users.tmp командой tee.
(казалось-бы, причём тут чай? ;) )

#120909

отсюда: http://linuxforum.ru/viewtopic.php?pid=136125#p136125

drBatty написал:

FROM=`sed -rn 's/^From:\s+[^<]*<([^> ]+)>.*/\1/;T;p;q' "$FILE_NAME"`
CRC=`sed -rn '/^Content-Type:\s+/,$p' "$FILE_NAME" | cksum | sed 's/ .*//'`

Страшно? Если вы - пользователь windows, то лучше вешайтесь. Если виндовс-админ - убейтесь ап сервер.

Остальные могут читать дальше: :D

наша цель - найти одинаковую почту от одинаковых авторов. причём почты РЕАЛЬНО МНОГО, потому представляется бредом сравнивать каждое сообщение с каждым (для этого потребуется N*N сравнений, и для одного из моих почтовых ящиков N (число постов) равно 1610. столько ждать мы устанем, даже если перепишем код на Си). Решение простое - нужно свернуть каждый пост в одну строчку, и записать эти строчки в файл.

Первым делом выдёргиваем мыло автора поста, например вот этого:

text
From: <admin@drbatty.ru>

Видно, что строка начинается на From:, после которого идут несколько пробелов, потом ещё что-то но не < (в этом примере этого нет), потом идёт <, потом нужный нам адрес в котором нет пробелов и >, а потом идёт >, и ещё что-то. Запишем выделенное короче, регуляркой: ^From:\s+[^<]*<([^> ]+)>.*

нам достаточно только первого адреса (некоторые письма содержат 2 адреса), для чего и стоит T;p;q

Содержимым письма считается все строчки начиная с Content-Type:, и до последней строки. Т.е. /^Content-Type:\s+/,$.

Его я пересылаю в команду cksum, которая вычисляет CRC32, и его печатает. Правда она ещё мусор в виде имени файла печатает (прочерк в данном случае), потому понадобилась ещё одна sed для фильтрации мусора.

вот и всё. Дальше можно сортировать строчки и удалить все не повторяющиеся:
[console]sort | uniq -d[/console]

#206915

ПОМОГИТЕ ПОЖАЛУЙСТА!!!!!!!!!!!!!!!!
ОЧЕНЬ НАДО!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

написать shell процедуру которая:
выводит на экран список всех пользователей системы включенных в заданную первым параметром группу пользователей
для каждого из заданных третьим и следующими параметрами имен пользователей выводит на экран права доступа к заданному вторым параметром файлу

Войдите или зарегистрируйтесь, чтобы ответить.