O comando grep no shell script

3

Eu tenho escrito um script de shell que deve fazer saídas de comando grep para uso posterior. No entanto, quando eu passar uma variável contendo ~/.../multiple_dir/* para grep como entrada recebo arquivo de saída vazio.

#!/bin/sh

set -u

PROGRAM="$1"
REGEXP=$(cat "$2")
INP_FILE="$3"
OUT_FILE="$4"

printf "%-30s: " $(basename ${INP_FILE})

if [ $INP_FILE = "STDIN.inp" ]
then
    cat ${INP_FILE} | ${PROGRAM} ${REGEXP} - > ${OUT_FILE} 2>&1
elif [ $INP_FILE = "MULTIPLE.inp" ]
then
    ${PROGRAM} ${REGEXP} '$(cat ${INP_FILE})' > ${OUT_FILE} 2>&1
else
    ${PROGRAM} ${REGEXP} ${INP_FILE} > ${OUT_FILE} 2>&1
fi

true

Este é o script que eu escrevi, com arquivos únicos ou de STDIN, funciona como um encanto, mas quando $(cat ${INP_FILE})=~/.../multiple_dir/* não funciona.

Eu tenho os diretórios ./inputs , ./inputs/multiple_dir/ e ./tests . No diretório ./tests , tenho um link para os arquivos de diretório ./inputs , que são SINGLE ( pdb file), STDIN ( pdb file que eu transmitirei como STDIN), UNREADABLE (sem bit de leitura), MULTIPLE ( contém ~/.../inputs/multiple_dir/* ) e EMPTY (vazio).

Eu tenho um Makefile que chama o shell script e passa um arquivo de cada vez como um parâmetro. Cada caso funciona perfeitamente, exceto quando passa MULTIPLE, então eu recebo um arquivo de saída vazio. Em todos os outros casos, os arquivos de saída não estão vazios. Os valores que o makefile passa para o script são os seguintes grep regExp/regExp(contains text ATOM) tests/MULTIPLE.inp(contains text ~/.../inputs/multiple_dir/*) outputs/MULTIPLE.out

Para ilustrar melhor o problema que estou tendo, escrevi alguns scripts curtos.

#!/bin/sh
grep ATOM ~/5as-darbas/inputs/multiple_dir/* > working.out

#!/bin/sh
input_file="$1"
#$1 is a file containing text ~/.../inputs/multiple_dir/*
echo "$(cat ${input_file})"
grep ATOM "$(cat ${input_file})" > not_working.out

Os resultados dos scripts são os seguintes:

simas@Lenovo:~/5as-darbas/inputs$ ./working 
simas@Lenovo:~/5as-darbas/inputs$ ./not_working MULTIPLE
~/5as-darbas/inputs/multiple_dir/*
grep: ~/5as-darbas/inputs/multiple_dir/*: No such file or directory
simas@Lenovo:~/5as-darbas/inputs$ ls -l
total 2372
-rw-rw-r-- 1 simas simas       0 Dec 10 19:37 EMPTY
-rw-rw-r-- 1 simas simas      35 Dec 12 02:49 MULTIPLE
-rw-rw-r-- 1 simas simas      25 Dec 12 02:43 MULTIPLE~
drwxrwxr-x 3 simas simas    4096 Dec 12 01:52 multiple_dir
-rwxr-xr-x 1 simas simas     163 Dec 12 03:26 not_working
-rw-rw-r-- 1 simas simas     161 Dec 12 03:26 not_working~
-rw-rw-r-- 1 simas simas       0 Dec 12 03:29 not_working.out
-rw-rw-r-- 1 simas simas       0 Dec 12 01:52 s~
-rw-rw-r-- 1 simas simas  332343 Dec 10 19:38 SINGLE
-rw-rw-r-- 1 simas simas  252720 Dec 10 19:38 STDIN
--w--w---- 1 simas simas  252720 Dec 10 19:38 UNREADABLE
-rwxr-xr-x 1 simas simas      70 Dec 12 03:27 working
-rw-rw-r-- 1 simas simas     128 Dec 12 03:27 working ~
-rw-rw-r-- 1 simas simas 1554999 Dec 12 03:29 working.out

Observe o tamanho de working.out e not_working.out.

Consegui que esse script funcionasse. A coisa é quando você passar um caminho ~/path/to/somewhere/* shell por algum motivo não pode encontrá-lo, no entanto, se você passar caminho como este /home/name/path/to/somewhere/* funciona como encanto.

    
por Simas.B 12.12.2013 / 00:56

3 respostas

1

Este é o erro que você recebe se tentar pesquisar em um diretório vazio:

$ tree
.
├── dir
│   └── file
└── empty_dir

2 directories, 1 file
$ grep foo dir/*  ## works, no error
$ grep foo empty_dir/*
grep: empty_dir/*: No such file or directory

Basicamente, quando você executa algo como grep ./* , o glob ( * ) é interpretado pelo shell que irá expandi-lo para o conteúdo do diretório que você forneceu. Se o diretório estiver vazio, isso se expandirá para nada e o shell retornará um erro. Você receberá o mesmo erro, independentemente do programa que você usa:

$ ls empty_dir/*
ls: cannot access empty_dir/*: No such file or directory

Então, suponho que ~/5as-darbas/inputs/multiple_dir/ esteja vazio. Isso não é grande coisa e você pode simplesmente ignorar o erro. Se você quiser lidar com isso mais facilmente, você poderia dar o nome do diretório (no glob) e executar um recursivo grep :

$ grep -R foo empty_dir/

Para fazer isso com sua configuração atual, altere '~/5as-darbas/inputs/multiple_dir/* para ~/5as-darbas/inputs/multiple_dir/ e atribua grep -R como o primeiro argumento ao seu script:

$ myscript.sh 'grep -R' regExp/regExp tests/MULTIPLE.inp outputs/MULTIPLE.out
    
por 12.12.2013 / 06:32
2

Tente usar eval em sua declaração. O Eval irá avaliar o valor de $ INP_FILE antes de os identificar.

de

${PROGRAM} ${REGEXP} '$(cat ${INP_FILE})' > ${OUT_FILE} 2>&1

para

${PROGRAM} ${REGEXP} $(eval cat ${INP_FILE}) > ${OUT_FILE} 2>&1
    
por 12.12.2013 / 01:40
1

Ignore tudo isso, eu estava pensando que o REGEXP estava incorretamente seguro guardado.

#! / bin / sh     grep "$ (cat $ 1)" $ 2

Este caso simples funciona com arquivos de entrada

tmp*

e

tmpfile

Chamado como

greptest re_file file_to_be_inspected
    
por 12.12.2013 / 01:05