Автор Тема: bash script четене на данни от файл  (Прочетена 2026 пъти)

mrowcp

  • Напреднали
  • *****
  • Публикации: 450
    • Профил
Въпроса ми е следния :)
имам файл от вида:

Цитат
cat file.txt

Jun  7 20:29:04 transport vsftpd[6050]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt", 39229 bytes, 383.10Kbyte/sec
Jun  7 20:29:05 transport vsftpd[6053]: DELETE: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt"
Jun  7 20:29:13 transport vsftpd[6070]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt", 28745 bytes, 280.71Kbyte/sec
Jun  7 20:29:14 transport vsftpd[6073]: DELETE: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt"

как да направя така, че за всяко име на файл да проверява дали има ред с действието DOWNLOAD и друг ред с DELETE?
Опитах да сравня броя на редовете с DELETE дали е равен на с DOWNLOAD, но тогава не мога да върна отговор за кой ред ( име на файл ) има само DELETE или само DOWNLOAD.
Другото което си мисля е, че може да проверявам за всяко име на файл дали има два реда:

Код:
cat messages |grep 0220100607200903.txt |awk '{print $8}'
DOWNLOAD:
DELETE:

но пък не знам как да задам да изчита всички ( едно по едно ) имена на файлове и тогава да проверява дали има DOWNLOAD и DELETE за тях.
Активен

Some Things Just Are The Way They Are

betso

  • Напреднали
  • *****
  • Публикации: 281
    • Профил
Re: bash script четене на данни от файл
« Отговор #1 -: Jun 07, 2010, 21:12 »
Опитай с нещо такова:
Цитат
FILE=file.txt
cd /home/user/Data/
for i in *.txt
do
  grep "$i" $FILE | grep DOWNLOAD && \
  grep "$i" $FILE | grep DELETE && \
  echo "\"$i\" беше свален и тутакси изтрит."
done
Успех! :)
Активен

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: bash script четене на данни от файл
« Отговор #2 -: Jun 07, 2010, 21:22 »
Струва ми се, че предложението по-горе не е за това, което питаш, така че ще ти пусна и една моя интерпретация
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. awk '{ print $9 }' $1 | cut -d'"' -f2 | awk '!x[$0]++' | while read i
  4. do
  5.    result=$i
  6.    cat $1 | grep $i | grep 'DOWNLOAD' &>/dev/null
  7.    if [ $? -ne 1 ] ; then
  8.        result=$result" : DOWNLOAD"
  9.    fi
  10.    cat $1 | grep $i | grep 'DELETE' &>/dev/null
  11.    if [ $? -ne 1 ] ; then
  12.        result=$result" : DELETE"
  13.        echo $result
  14.    else
  15.        echo $result
  16.    fi
  17. done
Ползвам $1 за име на файла, така че трябва да изпълняваш скрипта така
Код
GeSHi (Bash):
  1. ./script file.txt
Ако не искаш да е с $1, замени го с каквото ти е удобно ;)
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

radoulov

  • Напреднали
  • *****
  • Публикации: 116
    • Профил
Re: bash script четене на данни от файл
« Отговор #3 -: Jun 07, 2010, 23:36 »
Код:
awk -F, 'END {
  for ( __ in _ )
    if (_[__])
  print "No download/delete for", __
  }
/DOWNLOAD:/ { _[$2]++ }
/DELETE:/   { _[$2]-- }
  ' infile
« Последна редакция: Jun 07, 2010, 23:44 от radoulov »
Активен

mrowcp

  • Напреднали
  • *****
  • Публикации: 450
    • Профил
Re: bash script четене на данни от файл
« Отговор #4 -: Jun 08, 2010, 21:01 »
Мерси на всички който писаха.Ето до къде я докарах:
тествах 1во:

Опитай с нещо такова:
Цитат
FILE=file.txt
cd /home/user/Data/
for i in *.txt
do
  grep "$i" $FILE | grep DOWNLOAD && \
  grep "$i" $FILE | grep DELETE && \
  echo "\"$i\" беше свален и тутакси изтрит."
done
Успех! :)

но при директен c/p не вади резултат.След малко борене я докарах до някъде, но се отказах.Липсват ми все още явно доста познания :)


После пробвах:

Струва ми се, че предложението по-горе не е за това, което питаш, така че ще ти пусна и една моя интерпретация
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. awk '{ print $9 }' $1 | cut -d'"' -f2 | awk '!x[$0]++' | while read i
  4. do
  5.    result=$i
  6.    cat $1 | grep $i | grep 'DOWNLOAD' &>/dev/null
  7.    if [ $? -ne 1 ] ; then
  8.        result=$result" : DOWNLOAD"
  9.    fi
  10.    cat $1 | grep $i | grep 'DELETE' &>/dev/null
  11.    if [ $? -ne 1 ] ; then
  12.        result=$result" : DELETE"
  13.        echo $result
  14.    else
  15.        echo $result
  16.    fi
  17. done
Ползвам $1 за име на файла, така че трябва да изпълняваш скрипта така
Код
GeSHi (Bash):
  1. ./script file.txt
Ако не искаш да е с $1, замени го с каквото ти е удобно ;)

резултат е, че прави точно това което искам  ;D .Бих помолил neter или може и някои др да каже каква е ролята на:

!x[$0]++ - чете само повтарящите се редеве като... :)


Код:
awk -F, 'END {
  for ( __ in _ )
    if (_[__])
  print "No download/delete for", __
  }
/DOWNLOAD:/ { _[$2]++ }
/DELETE:/   { _[$2]-- }
  ' infile

Честно да си призная, още съм доста в началото и не можах да подкарам тоя код... :(
Активен

Some Things Just Are The Way They Are

radoulov

  • Напреднали
  • *****
  • Публикации: 116
    • Профил
Re: bash script четене на данни от файл
« Отговор #5 -: Jun 08, 2010, 22:01 »
Цитат
Честно да си призная, още съм доста в началото и не можах да подкарам тоя код... :(

Пробвай така:

Код:
zsh-4.3.10[t]% cat infile
Jun  7 20:29:04 transport vsftpd[6050]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt", 39229 bytes, 383.10Kbyte/sec
Jun  7 20:29:05 transport vsftpd[6053]: DELETE: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt"
Jun  7 20:29:06 transport vsftpd[6050]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt", 39229 bytes, 383.10Kbyte/sec
Jun  7 20:29:13 transport vsftpd[6070]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt", 28745 bytes, 280.71Kbyte/sec
Jun  7 20:29:14 transport vsftpd[6073]: DELETE: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt"
zsh-4.3.10[t]% awk -F, 'END {
  for ( __ in _ )
    if (_[__])
  print "No download/delete for", __
  }
/DOWNLOAD:/ { _[$2]++ }
/DELETE:/   { _[$2]-- }
  ' infile
No download/delete for  "/home/user/Data/0120100607202850.txt"

Активен

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: bash script четене на данни от файл
« Отговор #6 -: Jun 08, 2010, 22:28 »
Бих помолил neter или може и някои др да каже каква е ролята на:

!x[$0]++ - чете само повтарящите се редеве като... :)
Игнорира редовете, които се явяват повторение на вече прочетен преди това ред. Т.е., премахва повтарящите се редове. Тъй като при първото прочитане на файла вземам само имената на файловете, то без тази част, за която питаш, изходът от awk щеше да е:
Цитат
/home/user/Data/0120100607202850.txt
/home/user/Data/0120100607202850.txt
/home/user/Data/0120100607202850.txt
/home/user/Data/0220100607202843.txt
/home/user/Data/0220100607202843.txt
Като добавим и втория awk, крайният изход от реда е:
Цитат
/home/user/Data/0120100607202850.txt
/home/user/Data/0220100607202843.txt
Така вземам чист списък с имената на файловете, описани в твоя файл, след което проверявам за всеки от тях дали има ред с "DOWNLOAD" и дали има ред с "DELETE". Скриптът може да се скъси още, синтаксисът на radoulov също е добър, но реших да ти пусна по-лесен за четене скрипт, за да разбереш какво се случва в него. Успех ;)
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

mrowcp

  • Напреднали
  • *****
  • Публикации: 450
    • Профил
Re: bash script четене на данни от файл
« Отговор #7 -: Jun 13, 2010, 13:22 »
Бих помолил neter или може и някои др да каже каква е ролята на:

!x[$0]++ - чете само повтарящите се редеве като... :)
Игнорира редовете, които се явяват повторение на вече прочетен преди това ред. Т.е., премахва повтарящите се редове. Тъй като при първото прочитане на файла вземам само имената на файловете, то без тази част, за която питаш, изходът от awk щеше да е:
Цитат
/home/user/Data/0120100607202850.txt
/home/user/Data/0120100607202850.txt
/home/user/Data/0120100607202850.txt
/home/user/Data/0220100607202843.txt
/home/user/Data/0220100607202843.txt
Като добавим и втория awk, крайният изход от реда е:
Цитат
/home/user/Data/0120100607202850.txt
/home/user/Data/0220100607202843.txt
Така вземам чист списък с имената на файловете, описани в твоя файл, след което проверявам за всеки от тях дали има ред с "DOWNLOAD" и дали има ред с "DELETE". Скриптът може да се скъси още, синтаксисът на radoulov също е добър, но реших да ти пусна по-лесен за четене скрипт, за да разбереш какво се случва в него. Успех ;)

Мерси :) По скоро имах предвид как се тълкува !x[$0] за ++ е ясно :)
Също така когато изпълня скрипта на FreeBSD-то ми изписва:


Usage: grep [OPTION]... PATTERN [FILE]...
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Try `grep --help' for more information.

,но пък си работи :)

Цитат
Честно да си призная, още съм доста в началото и не можах да подкарам тоя код... :(

Пробвай така:

Код:
zsh-4.3.10[t]% cat infile
Jun  7 20:29:04 transport vsftpd[6050]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt", 39229 bytes, 383.10Kbyte/sec
Jun  7 20:29:05 transport vsftpd[6053]: DELETE: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt"
Jun  7 20:29:06 transport vsftpd[6050]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0120100607202850.txt", 39229 bytes, 383.10Kbyte/sec
Jun  7 20:29:13 transport vsftpd[6070]: DOWNLOAD: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt", 28745 bytes, 280.71Kbyte/sec
Jun  7 20:29:14 transport vsftpd[6073]: DELETE: Client "192.168.1.1", "/home/user/Data/0220100607202843.txt"
zsh-4.3.10[t]% awk -F, 'END {
  for ( __ in _ )
    if (_[__])
  print "No download/delete for", __
  }
/DOWNLOAD:/ { _[$2]++ }
/DELETE:/   { _[$2]-- }
  ' infile
No download/delete for  "/home/user/Data/0120100607202850.txt"


Дето има един лаф: Work like a charm! :) Честно не вярвах, че това нещо ще проработи  :o , но определено мн ми хареса резултата.Жалко, че нищо не разбрах :(
« Последна редакция: Jun 13, 2010, 13:24 от mrowcp »
Активен

Some Things Just Are The Way They Are

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: bash script четене на данни от файл
« Отговор #8 -: Jun 13, 2010, 14:43 »
По скоро имах предвид как се тълкува !x[$0] за ++ е ясно :)
Awk разделя съдържанието в редовете на колони, спрямо някакъв разделител, подреждайки последователно всеки елемент в променливи $1, $2, $3 и т.н. Променливата $0 означава да се вземе целият ред. Тъй като преди това съм изчистил реда от останалите неща с предшестващите awk и cut команди, то в този случай целият ред се явява името на файла с пътя му (например /home/user/Data/0120100607202850.txt).
В awk можеш да задаваш стойности на аргументи, чиито стойности да използваш след това. В случая сме кръстили нашия аргумент x[], но можеш да го кръстиш както искаш. Този аргумент ще съдържа масив от имената на файловете. Т.е., в процеса на изпълнение аргументът ще добие последователно тези стойности:
Цитат
x['/home/user/Data/0120100607202850.txt'] = 1;
x['/home/user/Data/0120100607202850.txt'] = 2;
x['/home/user/Data/0120100607202850.txt'] = 3;
x['/home/user/Data/0220100607202843.txt'] = 1;
x['/home/user/Data/0220100607202843.txt'] = 2;
При всяко изпълнение стойността на аргументът се увеличава с единица, благодарение на ++.
Удивителната пред параметрите ни добавя условие редът да бъде изведен на екрана, ако стойността за този аргумент не е зададена, т.е. ако описаната променлива не е дефинирана. Да вземем за пример файла /home/user/Data/0120100607202850.txt. За него в аргумента x[] се създава елемент с име x['/home/user/Data/0120100607202850.txt']. При първото завъртане на while, стойността на x['/home/user/Data/0120100607202850.txt'] все още не е дефинирана (редът все още не е бил срещан), редът се извежда, и се дефинира x['/home/user/Data/0120100607202850.txt'] = 1. При следващото завъртане на while отново се среща файлът /home/user/Data/0120100607202850.txt, но x['/home/user/Data/0120100607202850.txt'] вече е дефиниран, така че редът не се извежда, а само се увеличава стойността на аргумента. Това се случва и със следващите срещания на този ред - аргументът е дефиниран, редът не се извежда, и в крайна сметка се извежда само първото срещане на реда, тъй като само тогава стойността на аргумента не е дефинирана. Същото се случва и с редовете за другите файлове.

Също така когато изпълня скрипта на FreeBSD-то ми изписва:

Usage: grep [OPTION]... PATTERN [FILE]...
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Try `grep --help' for more information.

,но пък си работи :)
Обърни внимание, че ползваш различни shell-ове по подразбиране под Linux и под FreeBSD. Тъй като искаше bash скрипт, при изписването не се съобразих с другите shell-ове. Под FreeBSD най-вероятно използваш sh, а не bash (можеш да видиш кой потребител с кой shell работи във файла /etc/passwd). Тъй като sh е малко по-чувствителен от bash при изписването на аргументи със специални символи, скриптът вади грешка при grep-овете за променливата $i на тези два реда:
Код
GeSHi (Bash):
  1. cat $1 | grep $i | grep 'DOWNLOAD' &>/dev/null
  2. cat $1 | grep $i | grep 'DELETE' &>/dev/null
За да го оправиш, огради променливата $i на тези два реда с единични кавички. Т.е., да станат така:
Код
GeSHi (Bash):
  1. cat $1 | grep '$i' | grep 'DOWNLOAD' &>/dev/null
  2. cat $1 | grep '$i' | grep 'DELETE' &>/dev/null
« Последна редакция: Jun 13, 2010, 14:45 от neter »
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

mrowcp

  • Напреднали
  • *****
  • Публикации: 450
    • Профил
Re: bash script четене на данни от файл
« Отговор #9 -: Jun 14, 2010, 18:09 »
Мерси за изчерпателния отговор :) Вече ми попросветна ;)
Активен

Some Things Just Are The Way They Are

Подобни теми
Заглавие Започната от Отговора Прегледи Последна публикация
Bash script и извеждането му
Web development
martien 3 3408 Последна публикация Nov 02, 2006, 11:55
от morbid_viper
Bash script за следене съдържанието на директория
Общ форум
mishot 9 4401 Последна публикация Mar 05, 2008, 00:38
от maniac
Bash script
Общ форум
vikktor 14 5402 Последна публикация Mar 04, 2009, 23:38
от CappY
Помощ за bash script
Общ форум
LinuxFanUNIX 4 2922 Последна публикация May 15, 2009, 23:05
от LinuxFanUNIX
bash script
Общ форум
samiboy 3 1612 Последна публикация May 26, 2009, 06:45
от Hapkoc