Относительно UNIX Grep Command - PullRequest
       9

Относительно UNIX Grep Command

0 голосов
/ 22 февраля 2010

Мне нужно написать сценарий оболочки, который выбирает все файлы (не каталоги) в каталоге / exp / files. Для каждого файла в каталоге я хочу узнать, получена ли последняя строка файла. Последняя строка в файле - это трейлер. Также третье поле в последней строке - это количество записей данных, т.е. 2315 (Общее количество строк в файле -2 (заголовок, трейлер)). В моем сценарии оболочки Unix я хочу проверить, является ли последняя строка записью трейлера, проверив T, и хочу проверить, равно ли число строк в файле (2315 + 2). Если это успешно, то я хочу переместить файл в другой каталог / exp / ready.

tail -1 test.csv 
T,Test.csv,2315,80045.96

Также во входном файле иногда в двойных кавычках может быть еще 0 или 1 поле записи трейлера.

"T","Test.csv","2315","80045.96"
"T", Test.csv, 2212,"80045.96"
T,Test.csv,2315,80045.96

Ответы [ 6 ]

1 голос
/ 22 февраля 2010

Этот код выполняет все логические вычисления с помощью одного вызова awk, что делает его очень эффективным.Он также NOT жестко кодирует значение примера 2315, но скорее использует значение, содержащееся в строке трейлера, так как я считаю, что это было вашим намерением.

Не забудьте удалить echo, если вы удовлетворены результатами.

#!/bin/bash

for file in /exp/files/*; do
  if [[ -f "$file" ]]; then
    if nawk -F, '{v0=$0;v1=$1;v3=$3}END{gsub(/"/,"",v0);exit !(v1 == "T" && NR == v3+2)}' "$file"; then
      echo mv "$file" /ext/ready
    fi
  fi
done

Обновление

Мне пришлось добавить {v0=$0;v1=$1;v3=$3}, потому что реализация SunOS для awk делаетне поддерживает END {}, имеющий доступ к переменным поля ($ 0, $ 1, $ 2 и т. д.), но вместо этого должен быть сохранен в пользовательскую переменную, если вы хотите работать с ними внутри END {}.См. Последний ряд первой таблицы в Ссылка для сравнения этой функции awk

1 голос
/ 22 февраля 2010

Вы можете проверить наличие последней строки следующим образом:

tail -1 ${filename} | egrep '^T,|^"T",' >/dev/null 2>&1
rc=$?

В этот момент $rc будет 0, если строка начинается с T, или "T",, при условии, что этого достаточно, чтобы поймать запись трейлера.

Как только вы установили это, вы можете извлечь количество строк с помощью:

lc=$(cat ${filename} | wc -l)

и вы можете получить ожидаемый счетчик строк с помощью:

elc=$(tail -1 ${filename} | awk -F, '{sub(/^"/,"",$3);print 2+$3}')

и сравните их.

Так что, связав все это вместе, это было бы хорошим началом. Он выводит сам файл (мои тестовые файлы num[1-9].tst) вместе с сообщением, указывающим, в порядке ли файл или почему он не в порядке.

#!/bin/bash
cd /exp/files
for fspec in *.tst ; do
    if [[ -f ${fspec} ]] ; then
        cat ${fspec} | sed 's/^/   /'
        tail -1 ${fspec} | egrep '^T,|^"T",' >/dev/null 2>&1
        rc=$?
        if [[ ${rc} -eq 0 ]] ; then
            lc=$(cat ${fspec} | wc -l)
            elc=$(tail -1 ${fspec} | awk -F, '{sub(/^"/,"",$3);print 2+$3}')
            if [[ ${lc} -eq ${elc} ]] ; then
                echo '***' File ${fspec} is done and dusted.
            else
                echo '***' File ${fspec} line count mismatch: ${lc}/${elc}.
            fi
        else
            echo '***' File ${fspec} has no valid trailer.
        fi
    else
        ls -ald ${fspec} | sed 's/^/   /'
        echo '***' File ${fspec} is not a regular file.
    fi
done

Пример прогона, показывающий используемые мной тестовые файлы:

   H,Test.csv,other rubbish goes here
   this file does not have a trailer
*** File num1.tst has no valid trailer.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with all quotes and correct count
   "T","Test.csv","1","80045.96"
*** File num2.tst is done and dusted.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with all quotes but bad count
   "T","Test.csv","9","80045.96"
*** File num3.tst line count mismatch: 3/11.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with all quotes except T, and correct count
   T,"Test.csv","1","80045.96"
*** File num4.tst is done and dusted.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with no quotes on T or count and correct count
   T,"Test.csv",1,"80045.96"
*** File num5.tst is done and dusted.
   H,Test.csv,other rubbish goes here
   this file does have a traier with quotes on T only, and correct count
   "T",Test.csv,1,80045.96
*** File num6.tst is done and dusted.
   drwxr-xr-x+ 2 pax None 0 Feb 23 09:55 num7.tst
*** File num7.tst is not a regular file.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with all quotes except the bad count
   "T","Test.csv",8,"80045.96"
*** File num8.tst line count mismatch: 3/10.
   H,Test.csv,other rubbish goes here
   this file does have a trailer with no quotes and a bad count
   T,Test.csv,7,80045.96
*** File num9.tst line count mismatch: 3/9.
1 голос
/ 22 февраля 2010

Если вы хотите переместить файлы после того, как они были записаны и закрыты, вам следует подумать об использовании чего-то вроде inotify, incron, FAM, gamin и т. Д.

0 голосов
/ 22 февраля 2010
#!/bin/bash

ex findready.sh <<'HERE'
  i#!/bin/bash/

  let NUMLINES=$(wc -l $1)
  let TRAILER=$(cat $1 | tail -1 | tr -d '"' | sed 's/^\(.\).*$/\1/')

  if [[ $NUMLINES -eq 2317 && $TRAILER == "T" ]] ; then
      mv $1 /exp/ready/$1
  fi
  .
  wq
HERE

chmod a+x findready.sh

find /exp/files/ -type f -name '*.csv' -exec ./findready.sh {} ';' > /dev/null 2>&1
0 голосов
/ 22 февраля 2010
destination=/exp/ready
for file in /exp/files/*.csv
do
    var=$(tail -1 "$file" | awk -F"," '{ gsub(/\042|\047/,"") }
    $1=="T" && $3 == "2315" { print "ok" }')
    if [ "$var" = "ok" ]; then
        echo mv "$file" "$destination"
    else
        echo "invalid: $file"
    fi
done
0 голосов
/ 22 февраля 2010

Здесь нет удобной оболочки UNIX, но

#!/bin/bash
files=$(find /exp/files -type f)

должен поместить все файлы в массив BASH; затем итерирование каждого из них как paxdiablo , предложенное выше, должно вас отсортировать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...