[Linux] Домашно "Text Editors And Tools" - задача 2


4
2. With a single regular expression get all services that have the string 'file' in their names from /etc/services and are runing only on UDP.
Здравейте, ето как съм разбрала тази задача, вероятно ще имате забележки:
grep -i 'file&\/udp' /etc/services
Поздрави :)



Отговори



1
Задачата е интересна с това че първо е хубаво да се реши едно по-просто под-условие A) на тази задача 2):
"2.A Да се отпечатат редовете на всички услуги, описани само на един ред от файла /etc/services"

Е решението на подусловие А) е достатъчно занимателно и може да се формулира и като отделна задача. Едно възможно решение е следната команда:
cat /etc/services | cut -d " " -f1 | grep file | uniq -c | grep -E "1 " | awk '{ print $2 }' | for ii in $(xargs) ;do grep $ii /etc/services; done

Ще се радвам ако разсъжденията ми Ви се сторят полезни :-)

от kiril.ilarionov (1482 точки)


2

grep  -i  '.*file.*\/udp'  /etc/services

Горната команда намира услугите ползващи udp,
но е нужен механизъм за проверка на другите редове в които същата услуга се дефинира на друг протокол: ddcp, tcp, ...
 
Може би grep -i -A1 -B1 /RE/
или sed редактиращ цял файл ред по ред?
 

от kiril.ilarionov (1482 точки)


1
По принцип аз го мъча със sed, но не мога да намеря "AND" и само го принти като OR.
sed -n -e '/file/,/udp/p' /etc/services

от pinkie_Pie (17 точки)


0
Здравей, В задачата е казано "With a single regular expression "

от yulimoto (0 точки)


2

Здравейте,

според мен дилемата е дали може udp да бъде описано и като UDP. Проверих man services и man protocols и в двете udp беше написано с малки букви, което ме навежда на мисълта че това е някаква конвенция. Ето част от manual-а която дава яснота по синтаксиса на /etc/services

Each line describes one service, and is of the form:


              service-name   port/protocol   [aliases ...]

За низа 'file" е казано ясно - the string 'file' -  т.е. низа 'file' е различен от 'File' 'FILE' и т.н. Ето за това не бих използвал -i опция. 

Oпит при който регулярния израз да не е много хлабав направен според условието и прочетеното в man services :


grep --color=auto  -E '^[0-9A-Za-z_-]*file[0-9A-Za-z]*\>[[:space:]]+\<[0-9]{1,5}/udp\>'   /etc/services

ако udp допуска да бъде написано с главни букви може да се сложи (udp|UDP) или пък ако искаме да допусне случаи като тeзи uDp Udp UDp и т.н. - [Uu][Dd][Pp]

 

п.с. сигурно регулярния израз съдържа грешки или пък може още да се помисли. Вероятно може да се задълбае в  портовете, които в горния израз обхващат от 0-99999, което не е самата истина.


от yulimoto (0 точки)


0
0-65535 ;) портовете не са 100000.

от the_hex (30 точки)

0
да това казвам и аз - "горния израз обхващат от 0-99999, което не е самата истина".

от yulimoto (0 точки)



3
Аз използвах следното решение: grep 'file.*udp' /etc/services
Или може да се вкара цвят: grep --color=auto 'file.*udp' /etc/services

от guzunovbg (20 точки)


2

Yulimoto е прецизен, но за практични цели:

grep --color=auto -E 'file.*(\/udp|\/UDP)|(\/udp|\/UDP).*file' /etc/services
 
- will get all the lines that contain both “file” and “udp|UDP”  in any order.
 
 

от gianyy (176 точки)


0
Дали не е достатъчно и само това:
grep --color=auto -E 'file.*(\/udp|\/UDP)' /etc/services
Поне при мен така се получава без излишни редове (със стринг "file" в коментарите). В /etc/services на grizzly изрових 24 записа, отговарящи на условието.

от bonevdp (20 точки)

0
Хубаво е да се отравя по нещичко, но за поставената задача просто няма да се намерят редове отговарящи на условието.
@morena Резултат като Вашия може да се получи и с: grep -E 'file.*udp' /etc/services

от kiril.ilarionov (1482 точки)



4
tac services|sed -ne '/^[^#]*\s.*\/udp.*/{N;/\(^[^#]*\s.*\)\/udp\(.*\)#*.*\n\1\/tcp\2/!{s/\n.*//p}}'

Вярвам може да добавите частта с 'file' ;)
За поясненията ми погледнете:
http://blog.wonderboy.name/2013/08/16/sedregex-0wnage/

П.С. даже е по-лесно с
tac services|sed -ne '/^[^#]*\s.*\/udp.*/{N;/\(.*\)\/udp\(.*\)#*.*\n\1\/tcp\2/!{s/\n.*//p}}'
но утре ще радактирам обясненията



0
Здравейте !
От снощи се опитвам да достъпя Grizzly ( 85.14.7.110 ) , но ми дава само тайм аут :( ако може качете в GitHub "/var/spool/mail/root" и/или "/etc/services" - все пак искам да си предам домашното :)

от Anton Yankov (0 точки)

0
GitHub нямам, но ето ти /etc/services http://wonderboy.name/services.tar.gz




2
Здравейте,
засега това ми е най-сполучливия и "прост" RE с който успях да реша задачата:
awk '$1 ~/file/ && $2 ~/udp/ && $2 !~/tcp/{print $1,$2}' /etc/services
По този начин търся "file" само в 1вата колона като бягам от matches извън service-name използвайки $1 ~/file/
По същия начин match-вам само "udp" кадето го има и едновременно няма "tcp" във втората колона и за да дисплейна само колона 1 и 2 добавям {print $1,$2}.
Поздрави,
Александър

от alexaat (10 точки)


0
Колега, $2 като е равно на udp не ли в същото време различно от tcp, тоест третата проверка за !~ е малко безмислена или аз бъркам някъде? :)

от Ivaka (85 точки)

0
Резултата от командата с и без 3тата проверка дава идентичен резултат, добавих 3тата проверка тъй като условието завършва с "ONLY on UDP". Има услуги които работят както на tcp така и на udp, но заради формата на /etc/services наистина 2рата проверка изключва 3тата. Пример: domain 53/tcp # name-domain server domain 53/udp Както се вижда една и съща услуга ако работи на tcp и udp е записана на два реда, но както казах добавих 3тата проверка заради условието иначе в конкретния файл резултата е идентичен.

от alexaat (10 точки)