2016-11-07 2 views
2

Как передать аргументы функции или цикла в bash в моем случае ?. Разделителем поля будет пространство, а также следующая строка (\ n). Цель состоит в том, чтобы получить все команды маршрута из файла журнала, а затем повторно применить их, но удалять их перед применением.bash function pass space & line разделенные аргументы от sed

file.log

Mon Nov 7 10:55:28 2016 bla bla bla 
Mon Nov 7 10:55:28 2016 bla blabla bla 
Mon Nov 7 11:19:27 2016 /sbin/route add -net 123.123.123.0 123.123.123.104 255.255.240.0 
Mon Nov 7 11:19:27 bla bla bla 
Mon Nov 7 11:19:27 2016 /sbin/route add -net 111.111.111.111 192.168.1.1 255.255.255.255 
Mon Nov 7 11:19:32 2016 /sbin/route add -net 4.4.2.2 224.224.224.1 255.255.255.255 
Mon Nov 7 11:19:32 bla blabla bla 
Mon Nov 7 11:19:32 2016 /sbin/route add -net 222.222.222.222 224.224.224.1 255.255.255.255 
Mon Nov 7 11:20:21 bla blabla bla 
Mon Nov 7 11:20:21 bla bla bla 
Mon Nov 7 11:20:23 bla bla bla 

Следующие выдержки команды маршрута из файла журнала будут добавлены,

sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' /path/to/file.log | awk '!seen[$0]++' 

Вот что я пытаюсь с функцией Баш,

#!/bin/bash 

add_routes() { 

$1 delete $3 $4 $5 $6  #expecting: eg: /sbin/route delete -net 4.4.2.2 224.224.224.1 255.255.255.255 
[email protected]       #expecting: eg: /sbin/route add -net 4.4.2.2 224.224.224.1 255.255.255.255 


} 

add_routes $(sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' /path/to/file.log | awk '!seen[$0]++') 

Желаемая команда вывода, выполняемая последовательно из указанной функции (сначала удалите ее, чтобы применить последние Маршрутная сеть извлечена из журнала),

/sbin/route delete -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route add -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route delete -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route add -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route delete -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route add -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route delete -net 222.222.222.222 224.224.224.1 255.255.255.255 
/sbin/route add -net 222.222.222.222 224.224.224.1 255.255.255.255 

из приведенной выше функции, $ @ выполняет вставляя все команды маршрута в одной строке, которая терпит неудачу. И команда delete (выше $ @ line) удаляет только первый маршрут.

Кто-нибудь знает, как получить желаемый результат с функциями или с for loop, если он выполнит свою работу ?. Благодаря!

ответ

2

Вы можете это сделать в BASH без sed:

while read -r; do 
    read -ra arr <<< "/sbin/${REPLY#* /sbin/}" # strips anything before /sbin/ 
    [[ ${arr[0]} == /sbin/route ]] && 
    "${arr[@]/add/delete}" && 
    "${arr[@]}" 
done < file.log 

EDIT:

Вот одна команда AWK делать все:

awk '{sub(/^([^[:blank:]]+[[:blank:]]+){5}/, "")} $1 == "/sbin/route" && !seen[$0]++{ 
     s=$0; sub(/add/, "delete"); print; print s}' file.log | bash 
+0

К сожалению, в реальном файле журнала он не начинается с команды route, а префиксами с датой и временем. Это моя ошибка не для того, чтобы упорядочить файл.log. Кстати, я использую sed, чтобы избежать дублирования маршрутов. Я действительно не знаю, что мы можем сделать это с помощью bash, хорошо знать новые вещи. Удивление, если вы можете редактировать, чтобы он читал команду маршрута, даже если он не начинал сначала в строке ... – user465465

+0

Обновлен мой вопрос! – user465465

+0

NIce, небольшая проблема с сортировкой - я теряю последовательность, которую он должен выполнить по сравнению с awk. – user465465

1

Проблема с передачей вашей функции выход Команда d непосредственно есть, как вы видели, выход приходит в пространстве (я думаю).

Иногда вы увидите, как люди обходятся этим, играя в игры с IFS и OFS. Я всегда притворяюсь и думаю, что это выглядит грязно.

Я предпочитаю делать этот стиль цикла, потому что он работает так, как я ожидаю. Если вы запустите цикл for над файлом, он может интерпретировать пробелы в строке, поскольку новые строки и вещи становятся беспорядочными. http://www.compciv.org/topics/bash/loops/ Объясняет это и стоит прочитать.

Петля while read x; do ... done < <(cmd) стиль:

while read log_line;do 

    add_routes ${log_line} 

done < <(sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' file.log) 

В основном вы перенаправление вывода sed к ФИФО, а затем перенаправляет ФИФО в поток ввода read. read достаточно умен, чтобы читать в одной строке вывода sed в переменную log_line.

Теперь, когда log_line содержит одну строку вывода, вы просто передаете ее функции add_routes, как вы ее написали.

Иногда необходимо сделать read -r, если вы не хотите интерпретировать новые строки, но, очевидно, здесь вы делаете!

Полный пример ...

script.sh

#!/bin/bash 

add_routes(){ 
    echo "$1 delete $3 $4 $5 $6"; 
    echo [email protected]; 
} 

while read thing;do 

    add_routes ${thing} 

done < <(sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' file.log) 

file.log как вы положили его.

выход:

$ ./script.sh 
/sbin/route delete -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route add -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route delete -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route add -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route delete -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route add -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route delete -net 222.222.222.222 224.224.224.1 255.255.255.255 
/sbin/route add -net 222.222.222.222 224.224.224.1 255.255.255.255 

Обратите внимание, что я вторя из команд, которые вы хотели работать, так как я на самом деле не хочу возиться с моими маршрутами.

Для получения дополнительного чтения о Баше перенаправлении проверить http://www.catonmat.net/download/bash-redirections-cheat-sheet.pdf

+0

Приятная информация !. Я тестирую это, я вернусь и дам вам знать. Спасибо за ваш интерес! – user465465

+0

Ты стоишь щедрости, сейчас мне это не разрешено! – user465465

+0

Возможно, вы захотите сначала прочитать http://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice и основы google bash. 'read -r' не имеет ничего общего с интерпретацией новых строк. –

0

Вы передаете многострочный вывод sed к add_routes() в один проходе, когда add_routes() записываются обрабатывать только один маршрут.

Прямой ответ на ваш вопрос, без переписывания всего кода, заключается в использовании xargs, который может обрабатывать многострочные и передавать по add_routes() по одной строке за раз (или по 6 параметров).

Все, что вам нужно изменить эту строку:

add_routes $(sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' /path/to/file.log) 

Для этой линии:

sed -n 's/^.*\(\/sbin\/route\ add \-net\)/\1/p' /path/to/file.log | xargs -n6 add_routes 

-n 6 говорит xargs передать 6 параметры в то время.

Goodluck.

1
$ cat tst.sh 
awk 'sub(".*/sbin/route add ","") { 
    print "delete", $0 
    print "add", $0 
}' file | 
xargs -d $'\n' -n 1 echo /sbin/route 

$ ./tst.sh 
/sbin/route delete -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route add -net 123.123.123.0 123.123.123.104 255.255.240.0 
/sbin/route delete -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route add -net 111.111.111.111 192.168.1.1 255.255.255.255 
/sbin/route delete -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route add -net 4.4.2.2 224.224.224.1 255.255.255.255 
/sbin/route delete -net 222.222.222.222 224.224.224.1 255.255.255.255 
/sbin/route add -net 222.222.222.222 224.224.224.1 255.255.255.255 

Просто удалите echo, когда вы довольны командной строкой.

Если вы не имеете GNU xargs то -d аргумент не может быть недоступна, и тогда вы должны были бы использовать это вместо того, чтобы (не тестировалось):

awk -v ORS='\0' 'sub(".*/sbin/route add ","") { 
    print "delete", $0 
    print "add", $0 
}' file | 
xargs -0 -n 1 echo /sbin/route 
+0

'xargs: незаконный вариант - d использование: xargs [-0opt] [-E eofstr] [-I replstr [-R замены]] [-J replstr] [-L номер] [-n number [-x ]] [-P maxprocs] [-s size] [полезность [аргумент ...]] ' - FYI, я нахожусь OSX – user465465

+0

' -d' должен быть GNU-ism, извините, я не сделал знайте это. Можете ли вы установить GNU xargs? В любом случае я просто добавил версию, которая должна работать с любыми xargs, добавив '-v ORS = '\ 0'' в начале команды awk и заменив' -d $' \ n'' '-0' в команде xargs. –

+0

Не повезло, наверное, я должен рассмотреть возможность установки gnu-xargs. Я попробовал обновленный раздел awk, все маршруты вставляются в одну строку и/sbin/route добавляется только к первому удалению, а все остальные не сопровождаются/sbin/route. – user465465

0

Это может работать для вас (GNU СЭД) :

sed -nr '\#^.*(/sbin/route add)#{s//\1/;h;G;s/add/delete/ep}' file 

Этот фильтр файл с помощью сопоставления с образцом, а затем дублирует нужный вход и заменяет первое add по delete. Затем результат вычисляется.

Это также должно работать с большинством sed и shell;

sed -n '\#^.*\(/sbin/route add \)#{s//\1/;h;G;s/add/delete/p}' file | 
shell 
+0

'sed: незаконный вариант - r использование: sed script [-Ealn] [-i extension] [файл ...] sed [-Ealn] [-i extension] [-e script] ... [ f script_file] ... [file ...] '- Вероятно, я должен рассмотреть возможность использования gnu-sed в моем OSX, о котором вы уже упоминали. Мне нужно будет использовать это на нескольких узлах OSX и, главным образом, избегать дополнительной установки и просто пытаться с использованием нестандартного решения, поскольку пиво не может быть найдено и снова дополнительная работа !. Позвольте мне рассмотреть это в других случаях. – user465465

+0

@ user465465 см. Редактировать – potong

Смежные вопросы