Сінтаксічны канфігурацыйны файл у Баш

Вось мой канфігурацыйны файл (DansGuardian-канфігурацыі):

banned-phrase duck

banned-site allaboutbirds.org

Я хачу напісаць Баш скрыпт, які будзе чытаць гэты канфігурацыйны файл і стварыць іншыя файлы для мяне. Вось тое, што я да гэтага часу, гэта ў асноўным псеўда-код:

while read line
do
    # if line starts with "banned-phrase"
        # add rest of line to file bannedphraselist
    # fi

    # if line starts with "banned-site"
        # add rest of line to file bannedsitelist
    # fi
done < dansguardian-config

Я не ўпэўнены, калі мне трэба выкарыстоўваць Grep, SED, AWK, ці што.

Спадзяюся, што мае сэнс. Я проста сапраўды ненавіджу Dansguardian спісы.

4

6 адказы

З AWK :

$ cat config
banned-phrase duck frog bird
banned-phrase horse
banned-site allaboutbirds.org duckduckgoose.net
banned-site froggingbirds.gov

$ awk '$1=="banned-phrase"{for(i=2;i<=NF;i++)print $i >"bannedphraselist"}
       $1=="banned-site"{for(i=2;i<=NF;i++)print $i >"bannedsitelist"}' config

$ cat bannedphraselist 
duck
frog
bird
horse

$ cat bannedsitelist 
allaboutbirds.org
duckduckgoose.net
froggingbirds.gov

<�Моцны> Тлумачэнне:

У AWK па змаўчанні кожны радок падзяляецца на палі прабеламі, а кожнае поле апрацоўваецца $ я , дзе I з'яўляецца я й поле <�ет> т першае поле ў кожнай радку з'яўляецца $ 1 , то другое поле на кожнай лініі $ 2 ДА $ NF , дзе NF зменная, якая змяшчае шэраг палёў на дадзенай лініі.

Такім чынам, сцэнар просты:

  • Check the first field against our required strings $1=="banned-phrase"

  • If the first field matched then loop over all the other fields for(i=2;i<=NF;i++) and print each field print $i and redirect the output to the file >"bannedphraselist".

5
дададзена
Гэта менавіта тое, што мне трэба, але сінтаксіс так заблытана! Я думаю, мне трэба асвяжыць.
дададзена аўтар David Kennedy, крыніца
Выдатнае тлумачэнне! Дзякуючы.
дададзена аўтар David Kennedy, крыніца
Я дадаў кароткае тлумачэнне, спадзяюся, што гэта дапамагае. Вы можаце мець чытанне гэтага для поўнага ўвядзення ў AWK gnu.org /software/gawk/manual/gawk.pdf
дададзена аўтар Chris Seymour, крыніца
+1! Гэта адкрывае два файла апрацоўвае толькі адзін раз, што з'яўляецца gread перавагай. Гэта можа быць карацей і больш загадкавымі: AWK «/ ^ banned- (фраза | сайт)/{GSUB (/ - /" ", $ 1), для (я = 2; я <= NF; ++ я) пячатку $ я> $ 1 "спіс"} .
дададзена аўтар TrueY, крыніца

Вы маглі б зрабіць

sed -n 's/^banned-phrase *//p' dansguardian-config > bannedphraselist
sed -n 's/^banned-site *//p' dansguardian-config > bannedsitelist

Хоць гэта азначае, што чытанне файла двойчы. Я сумняваюся, што магчымая страта прадукцыйнасці мае значэнне, хоць.

4
дададзена
+1. Можна зрабіць гэта ў чыстым Баше, але ёсць прыкметны кампраміс паміж чысцінёй і бяспекай. З Sed вы можаце зрабіць гэта і бяспечна і чыста.
дададзена аўтар ruakh, крыніца

Вы можаце прачытаць некалькі зменных адразу; па змаўчанні яны падзеленыя на прабельных.

while read command target; do
  case "$command" in
    banned-phrase) echo "$target" >>bannedphraselist;;
    banned-site) echo "$target" >>bannedsitelist;;
    "") ;; # blank line
    *) echo >&2 "$0: unrecognized config directive '$command'";;
  esac
done < dansguardian-config

Проста ў якасці прыкладу. Разумная рэалізацыя будзе першым чытаць файлы спіс, пераканайцеся, што рэчы не былі ўжо забароненыя, і г.д.

4
дададзена
Мне падабаецца, як чытанае гэта (у параўнанні з AWK, СЭД і г.д.). Ці будзе гэта стаць значна больш складаным, калі канфігурацыйны файл меў такія радкі: забараніла-фразы качка фазан Mallard ? Ды i вы маглі б надрукаваць тыя на асобныя радкі ў выніковым файле?
дададзена аўтар David Kennedy, крыніца
Добры раствор. Нязначнае каментар: рэха тэкст >> файл будзе адкрыйце , lseek , блізка кожны раз, калі яна выклікаецца. Колькасць такіх выклікаў можа быць зменшана шмат, выкарыстоўваючы Exec 3 >> файл і рэха тэкст> & 3 .
дададзена аўтар TrueY, крыніца

What is the problem with all the solutions which uses echo text >> file? It can be checked with strace that in every such step the file is opened, then positioned to the end, then text is written and file is closed. So if there is 1000 times echo text >> file then there will be 1000 open, lseek, write, close. The number of open, lseek and close can be reduced a lot on the following way:

while read key val; do
  case $key in
  banned-phrase) echo $val>&2;;
  banned-site) echo $val;;
  esac
done >bannedsitelist 2>bannedphraselist 

Стандартны вывад і стандартны паток памылак перанакіроўваецца ў файл і застаецца адкрытым, пакуль цыкл жывы. Такім чынам, файлы адкрываюцца адзін раз і зачыняецца адзін раз. Няма неабходнасці lseek. Акрамя таго, кэшаванне файлаў больш выкарыстоўваецца такім чынам, як непатрэбныя выклікі Зачыніць не будзе вымываць буфераў кожны раз.

1
дададзена
while read name value
do
  if [ $name = banned-phrase ]
  then
    echo $value >> bannedphraselist
  elif [ $name = banned-site ]
  then
    echo $value >> bannedsitelist
  fi
done < dansguardian-config
0
дададзена

Лепш выкарыстоўваць AWK:

awk '$1 ~ /^banned-phrase/{print $2 >> "bannedphraselist"}
     $1 ~ /^banned-site/{print $2 >> "bannedsitelist"}' dansguardian-config
0
дададзена
@sudo_O: Гэты адказ заснаваны на гэта патрабаванне ад пытання: , калі радок пачынаецца з «забароненай-фразай» Таксама я не бачыў якіх-небудзь патрабаванняў мець больш за 1 фраз ў кожнай радку.
дададзена аўтар anubhava, крыніца
@sudo_O: Што рабіць, калі $ 1 гэта забараніла-phrase123 ?
дададзена аўтар anubhava, крыніца
Ня памылкова, што гэты намер за ўвод гэтай праверкі рэгулярных выразаў. Гэта тое, што гэта павінна адбыцца ў адпаведнасці з каментаром OP ў , калі радок пачынаецца з «забароненай-фразай» (не ведаю, сапраўдныя намеры)
дададзена аўтар anubhava, крыніца
матч Рэгулярнае выраз не патрабуецца, ні есці не дадаваць, і гэта працуе толькі для аднаго значэння ў кожнай радку.
дададзена аўтар Chris Seymour, крыніца
... гэта не значыць, што вы павінны выкарыстоўваць рэгулярныя выразы гэта, вядома, можа быць зроблена з дапамогай параўнання радкоў на першым полі.
дададзена аўтар Chris Seymour, крыніца
Тады ваша рашэнне будзе памылкова разабраць гэты радок і дадаць другое поле да аднаго з файлаў.
дададзена аўтар Chris Seymour, крыніца