Через скрипт я обрабатываю построчно некий текст для поиска совпадений по шаблону, столкнулся с такой проблемой...
после того как sed нашел совпадение в определнной строке, он ее должен вывести командой sed -n '$ENUM p' где $ENUM это каунтер с номером обрабатываемой строки, но так не получается вставить переменную - выпадает ошибка
sed: -e выражение #1, символ 3: лишние символы после команды
что за хреть...как мне вставить переменную в sed ...кто знает подскажите пожалуйста!?
P.S. Если вместо $ENUM написать допустим любую цифру, все работает - выводится соотв. строка.
Использование переменных в sed
Вопрос закрыт...сам дурак не попробовал вот так sed -n ''$ENUM' p'
создавайте подобные темы, пожалуйста, в более подходящих разделах
sed -n ''$ENUM' p'
зачем тут вообще кавычки-то?
Через скрипт я обрабатываю построчно некий текст для поиска совпадений по шаблону, столкнулся с такой проблемой...
после того как sed нашел совпадение в определнной строке, он ее должен вывести командой sed
эх... А одной командой это сделать не судьба? Обязательно надо получать какой-то номер, потом ещё команду с номером запускать...
facepalm.jpg
Если не поставить кавычки не будет работать
Например:
[root@localhost scripts]# temp_var=4
[root@localhost scripts]# ls -l | sed -n '4 p'
-rwxr-xr-x 1 root root 1388 Мар 13 14:44 get_hw_info
[root@localhost scripts]# ls -l | sed -n '$temp_var p'
sed: невозможно найти метку для перехода к `emp_var'
[root@localhost scripts]# ls -l | sed -n ''$temp_var' p'
-rwxr-xr-x 1 root root 1388 Мар 13 14:44 get_hw_info
[root@localhost scripts]#
[quote=vadoz]Через скрипт я обрабатываю построчно некий текст для поиска совпадений по шаблону, столкнулся с такой проблемой...
после того как sed нашел совпадение в определнной строке, он ее должен вывести командой sed
эх... А одной командой это сделать не судьба? Обязательно надо получать какой-то номер, потом ещё команду с номером запускать...
facepalm.jpg[/quote]
А как получить номер считываемой строки из цикла for?
В sed вроде = выводит номер, обрабатываемой строки.
Тогда
sed -n -e "/keyword/=" <inputfile> выведет номер строки со словом keyword.
А как получить номер считываемой строки из цикла for?
а разве вам этот номер нужен?
В sed вроде = выводит номер, обрабатываемой строки.
да. выводит, только не туда эта команда выводит :(
выведет номер строки со словом keyword.
выведет. только это не нужно. Кстати, -e тоже не нужно. А что нужно, ТС тщательно скрывает...
DATA_FOR_CHECK=`cat /etc/syslog.conf | sed -n '/^#/ !p' | sed -n '/^$/ !p' | sed s/' \+'/' '/g`
for i in ${`${DATA_FOR_CHECK} | cut -f1`};
do
.
.
.
Почему подстановка команды не работает в цикле ? for i in ${`${DATA_FOR_CHECK} | cut -f1`};
vadoz, эх... Мне не верите? Ну здесь почитайте что умные дядьки из IBM советуют: http://www.ibm.com/developerworks/aix/library/au-badunixhabits.html
Почему подстановка команды не работает в цикле ? for i in ${`${DATA_FOR_CHECK} | cut -f1`};
потому-что в вашем коде мне без стакана не разобраться. Как и вашему интерпретатору. Зачем такие сложности-то? У вас коммерческий проект, и вы боитесь, что ваш код будет украден конкурентами? :o
DATA_FOR_CHECK=`cat /etc/syslog.conf | sed -n '/^#/ !p' | sed -n '/^$/ !p' | sed s/' \+'/' '/g`
это четырёхэтажное матерное ругательство нужно сократить до одной команды sed. Причём ещё и проверить, что там оно вам возвращает. Вполне может быть, что совсем не то :(
Почему подстановка команды не работает в цикле ?
работает. только не так, как вы ожидаете.
DATA_FOR_CHECK=`cat /etc/syslog.conf | sed -n '/^#/ !p' | sed -n '/^$/ !p' | sed s/' \+'/' '/g`
Я с sed еще толком не разобрался, а так ....разбил на небольшие блоки и мне понятней потом самому в этом разобраться smile
Я с sed еще толком не разобрался, а так ....разбил на небольшие блоки и мне понятней потом самому в этом разобраться
вам это только так кажется. Начнём с того, что sed -n '/условие/!p' это масло масленное. Вам надо удалить строчку по условию? Ну так и пишите sed '/условие/d'
Далее, в одной команде можно сделать два действия. Например sed '/условие1/d; /условие2/d' (пробел после ; тут только для удобочитаемости)
Кроме того, простые условия можно группировать в одном регулярном выражении: sed -r '/условие1|условие2/d', но самое важное в том, что sed это УЖЕ цикл, который выполняется для всех строчек входного текста. ОЧЕНЬ плохая идея делать цикл с таким же циклом. Хотя-бы потому, что это непонятно и очень медленно.
sed s/' \+'/' '/g
вот это я с трудом понял. Замените на sed -r 's/\s+/ /', ибо это лучше читается, и обычно именно это и требуется (вы потом строчку в bash суёте, а для него всё едино, что пробелы, что табуляции, но вот \r может привести к проблемам. Хотя это тоже пробельный символ, но рисуется он совсем не как пробел).
| cut -f1
а вот этим вы чего хотели добиться? вывести всё до первого пробела? ну если уж вам не мила sed, которая это делает так sed 's/ .*//', дык дочитайте мануал cut до конца
-d, --delimiter=DELIM
use DELIM instead of TAB for field delimiter
что-то я сомневаюсь, что у вас в /etc/syslog.conf поля разделяются исключительно TAB'ом. (хотя от Red Hat можно ожидать и не такой гадости wink )
вывести всё до первого пробела? ну если уж вам не мила sed, которая это делает так sed 's/ .*//'
не понял это место...
. любой символ ,кроме \n.
Как
sed 's/ .*//' выведет все до первого пробела? или я не так понял цель этой штуки ,она ж все стирает
ИМХО, что-то вроде
sed 's/\s.*//' должно быть.
sed 's/ .*//'
не понял это место...
там не просто точка, а ПРОБЕЛ перед точкой. Потому удаляется не всё, а только первый пробел, и всё остальное. А вот s/.* // удаляет не всё до первого пробела, а всё до последнего.
sed 's/\s.*//'
должно быть.
ну можно и так конечно. Так оно даже лучше. Пустые строчки тоже надо удалять так s/^\s*$/, потому-что в пустых строчках могут быть пробельные символы. И на хвостах тоже могут быть. Из MS-DOS подобных ос постоянно приходят файлы с \r на конце.
. любой символ ,кроме \n.
неправильно. \n это тоже символ. И кстати тоже пробельный, и матчится и точкой и \s тоже. Другое дело, что sed обычно его хоть и читает, но в строчку для обработки не включает. Однако "обычно" не значит "всегда". Ну и ещё как всегда напомню, что точка матчит не всё. По стандарту с точкой совпадают любые символы, однако по другому стандарту, не все последовательности байтов в юникоде являются символами. Потому s/.*// ВНЕЗАПНО стала стирать не все строчки, и пришлось делать новую команду z для этого :(
Вообще цель скрипта - прочитать файл syslog.conf и проанализировать на наличие параметров отвечающих за регистрацию (допустим авторизации ) - параметр auth или authpriv.
Таким образом я командой DATA_FOR_CHECK=`cat /etc/syslog.conf | sed '/^#/d;/^$/d' | sed -r 's/\t+/ /;s/\s+/ /'` - записываю в переменную все параметры игнорируя закоменченные и пустые строки (sed '/^#/d;/^$/d'),
при этом между селекторами (auth или authpriv) и местом записи событий должен остаться один пробел для того, чтобы получилось два столбика из селекторов и места записи логов - вот так:
*.info;mail.none;authpriv.none;cron.none /var/log/messages
authpriv.info /var/log/secure
auth.* /var/log/secure-auth
daemon.* /var/log/daemon
mail.* -/var/log/maillog
cron.* /var/log/cron
*.emerg *
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
user.* /var/log/userlog
После чего выполняется вот эта хрень для сравления уровней важности сообщений....но оно еще не докончено....
#Уровень важности сообщений syslog
LEVEL[0]="emerg"
LEVEL[1]="alert"
LEVEL[2]="crit"
LEVEL[3]="err"
LEVEL[4]="warning"
LEVEL[5]="notice"
LEVEL[6]="info"
LEVEL[7]="debug"
LEVEL[8]="*"
#Построчное считывание параметров системы регистрации событий, записанных в переменную DATA_FOR_CHECK------------------------------------
for i in ${DATA_FOR_CHECK};
do
#Поиск параметров auth, authpriv отвечающих за безопасность и авторизацию в системе
if [[ ${i} == *"auth"* ]] || [[ ${i} == *"authpriv"* ]] || [[ ${i} == *"*."* ]]; then
for index in 0 1 2 3 4 5 6 7 8
do
VAR_TEMP=`cat /etc/syslog.conf | sed '/^#/d;/^$/d'| sed -r 's/\t+/ /' | sed -r 's/\s+/ /' | sed -n ''$N' p' | cut -f2`
if [[ ${i} == *"auth.""${LEVEL[index]}"* ]] || [[ ${i} == *"authpriv.""${LEVEL[index]}"* ]]; then
echo 'Параметры отвечающие за регистрацию событий авторизации ==>' "${i}"' ''записываются в файл ==>' "${VAR_TEMP}"
elif [[ ${i} == *"*.""${LEVEL[index]}"* ]] && [[ ${i} != *"authpriv.none"* && ${i} != *"auth.none"* ]]; then
echo 'Параметры отвечающие за регистрацию событий авторизации ==>' "${i}"' ''записываются в файл ==>' "${VAR_TEMP}"
break
fi
done
EXISTANS_FLAG=true
#Поиск ключевого слова "none" для параметров auth и auhpri, отменяющего регистрацию данных событий----------------------------------
if [[ ${i} == *auth.none* ]] || [[ ${i} == *authpriv.none* ]] || [[ ${i} == *"*.none"* ]]; then
FLAG=false
else
FLAG=true
fi
fi
N=$[ $N + 1 ]
done
А цель получить запись такого вида :
Параметры отвечающие за регистрацию событий авторизации ==> authpriv.info записываются в файл ==> auth.* /var/log/secure-auth
Параметры отвечающие за регистрацию событий авторизации ==> auth.* записываются в файл ==> mail.* -/var/log/maillog
Параметры отвечающие за регистрацию событий авторизации ==> *.emerg записываются в файл ==>
Только вот не могу понять почему в последней строчке:
Параметры отвечающие за регистрацию событий авторизации ==> *.emerg записываются в файл ==>
в конце не пишется * хотя она есть в конфиге???
там не просто точка, а ПРОБЕЛ перед точкой
мой косяк, не заметил)
Про . и \n читал в книге Девид Бизли Python: Полный справочник, стр 354. Дословно там написано:
. - любой символ, кроме символа перевода строки.
Наверняка это может быть отличием в трактовке питонячих регэкспов и регэкспов в sed (а вообще и перевода книги). Учту на будующее.
Вообще цель скрипта - прочитать файл syslog.conf и проанализировать на наличие параметров отвечающих за регистрацию (допустим авторизации ) - параметр auth или authpriv.
вроде вот эта утилита http://sourceforge.net/projects/watchlog/ делает тоже самое? Не?
Уровень важности сообщений syslog
а где у вас syslog читается?
echo 'Параметры отвечающие за регистрацию событий авторизации ==>' "${i}"' ''записываются в файл ==>' "${VAR_TEMP}"
почему нельзя написать так?
echo "Параметры отвечающие за регистрацию событий авторизации ==> ${i} записываются в файл ==>${VAR_TEMP}"зачем эта куча кавычек?
в конце не пишется * хотя она есть в конфиге???
я тоже с вашими кавычками запутался. Наверное bash эти звёздочки раскрыл. Он ведь все звёздочки раскрывает, что может. Просто * всегда раскрывается в список не скрытых файлов в текущем каталоге. Он у вас очевидно пуст.
if [[ ${i} == *"auth.""${LEVEL[index]}"* ]] || [[ ${i} == *"authpriv.""${LEVEL[index]}"* ]]; then
такой код называется write only. Написал, и больше НИКОГДА не трогай. :(
сотрите, и напишите нормально. Я ничего не понял.
Про . и \n читал в книге Девид Бизли Python
ну что касается юникода, то американцев этот вопрос слабо волнует, всякие перлы до сих пор считают Ф за два символа. Думаю пайтон не исключение, и тупо не умеет юникод(по умолчанию). Печально конечно, но что делать... А что касается \n, то тут вопрос намного более интересный, и дело тут в том, включен/выключен в ваших регулярках мультистрочный режим.
Не помню как в пайтоне, но в sed (а так же в перле, и в Over9000 других ЯП) мультистрочный режим таки ВЫКЛЮЧЕН.
[console]$ echo -e "a\nx" | sed 'N' # эта команда объединяет две строки в одну строчку с \n посередине.
a
x
# Ну всё равно это выглядит как 2 строки
$ echo -e "a\nx" | sed 'N;s/.*/+++/'
+++
# но вот меняется таки обе этих строчки, вместе с \n
$ echo -e "a\nx" | sed 'N;s/.*/+++/m' # в мультистрочном режиме sed учитывает, что строчек на самом деле две, и меняет не всё, а только первую строчку
+++
x
# первое совпадение...
$ echo -e "a\nx" | sed 'N;s/.*/+++/gm'
+++
+++
# или все совпадения но отдельно по строчкам[/console]
и да, читать надо info sed или мой перевод
«.» (точка)
Совпадает с любым одиночным символом, включая символ перевода строки.
лучше таки оригинал, ибо в этой вашей CentOS как всегда какая-нить древность :(
А ну, да:
[console]-bash-3.2# sed 'z'
sed: -e expression #1, char 1: unknown command: `z'
-bash-3.2# sed --version
GNU sed version 4.1.5
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
[/console]
не система, а полная задница :[
А как вывести элементы массива диапазоном ....ничего по этому поводу не нашел..либо все либо выборочно по инжексу элемента массива??
Вот массив как вывести допустим элементы со 2 по 8 не перечесляя их?
LEVEL[0]="*"
LEVEL[1]="emerg"
LEVEL[2]="alert"
LEVEL[3]="crit"
LEVEL[4]="err"
LEVEL[5]="warning"
LEVEL[6]="notice"
LEVEL[7]="info"
LEVEL[8]="debug"
А как вывести элементы массива диапазоном
только ручками, баш не питон...
ЗЫ: пользуйтесь тегами code/console для оформления....