Как правильно обрабатывать расширение подстановочных знаков в сценарии оболочки bash? - PullRequest
3 голосов
/ 03 ноября 2008
#!/bin/bash

hello()
{
    SRC=$1
    DEST=$2

    for IP in `cat /opt/ankit/configs/machine.configs` ; do
        echo $SRC | grep '*' > /dev/null
        if test `echo $?` -eq 0 ; then
            for STAR in $SRC ; do
                echo -en "$IP"
                echo -en "\n\t ARG1=$STAR ARG2=$2\n\n"
            done
        else
            echo -en "$IP"
            echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n"
        fi
    done
}

hello $1 $2

Выше приведен скрипт оболочки, который я предоставляю исходному (SRC) и деситнационному (DEST) пути. Это работало нормально, когда я не указывал путь SRC с подстановочным знаком ''. Когда я запускаю этот скрипт оболочки и даю ''. Pdf или '*' следующим образом:

root@ankit1:~/as_prac# ./test.sh /home/dev/Examples/*.pdf /ankit_test/as

Я получаю следующий вывод:

192.168.1.6
ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/home/dev/Examples/case_howard_county_library.pdf

DEST - это / ankit_test /, но DEST также манипулируется из-за '*'. Ожидаемый ответ

ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/ankit_test/as

Итак, если вы понимаете, что я пытаюсь сделать, пожалуйста, помогите мне решить эту ошибку. Я буду вам благодарен.

Заранее спасибо !!!

Мне нужно точно знать, как я использую * .pdf в своей программе один за другим, не нарушая DEST.

Ответы [ 9 ]

4 голосов
/ 03 ноября 2008

Ваш сценарий требует больше работы. Даже после экранирования, вы не получите ожидаемого ответа. Вы получите:

ARG1=/home/dev/Examples/*.pdf ARG2=/ankit__test/as

Попробуйте вместо этого:

for IP in `cat /opt/ankit/configs/machine.configs`
do
    for i in $SRC
    do
        echo -en "$IP"
        echo -en "\n\t ARG1=$i ARG2=$DEST\n\n"
    done
done

Запустите это так:

root@ankit1:~/as_prac# ./test.sh "/home/dev/Examples/*.pdf" /ankit__test/as
3 голосов
/ 03 ноября 2008

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

$ ls
one.pdf two.pdf three.pdf

и запустите ваш скрипт как

./test.sh *.pdf /ankit__test/as

будет таким же, как

./test.sh one.pdf two.pdf three.pdf /ankit__test/as

это не то, что вы ожидаете. Делая

./test.sh \*.pdf /ankit__test/as

должно работать.

2 голосов
/ 03 ноября 2008

Если вы можете, измените порядок параметров, передаваемых вашему сценарию оболочки, следующим образом:

./test.sh /ankit_test/as /home/dev/Examples/*.pdf

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

#!/bin/bash
hello()
{
    SRC=$1
    DEST=$2

    for IP in `cat /opt/ankit/configs/machine.configs` ; do
        echo -en "$IP"
        echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n"
    done
}

arg2=$1
shift
while [[ "$1" != "" ]] ; do
        hello $1 $arg2
        shift
done
1 голос
/ 02 августа 2012

Для нескольких входных файлов, использующих подстановочный знак, такой как * .txt, я обнаружил, что это работает отлично, экранирование не требуется. Он должен работать так же, как и собственное приложение bash, например, «ls» или «rm». Это нигде не было задокументировано, поэтому, потратив большую часть трех дней, пытаясь понять это, я решил опубликовать его для будущих читателей.

Каталог содержит следующие файлы (вывод ls)

file1.txt file2.txt file3.txt

Запустить скрипт как

$ ./script.sh *.txt

Или даже как

$ ./script.sh file{1..3}.txt

Сценарий

#!/bin/bash

# store default IFS, we need to temporarily change this
sfi=$IFS

#set IFS to $'\n\' - new line
IFS=$'\n'

if [[ -z $@ ]]
  then
  echo "Error: Missing required argument"
  echo
  exit 1
fi

# Put the file glob into an array
file=("$@")

# Now loop through them
for (( i=0 ; i < ${#file[*]} ; i++ ));
do

  if [ -w ${file[$i]} ]; then
     echo ${file[$i]} "  writable" 
  else
     echo ${file[$i]} " NOT writable"
  fi
done

# Reset IFS to its default value
IFS=$sfi

Выход

file1.txt writable
file2.txt writable
file3.txt writable

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

Теперь у вас есть список расширенных файлов ( с пропущенными пробелами ) в массиве file [], который вы затем можете просмотреть. Мне нравится это решение лучше всего, проще всего программировать и проще для пользователей.

1 голос
/ 05 ноября 2008

Вот что я придумал:

#!/bin/bash

hello()
{
    # DEST will contain the last argument
    eval DEST=\$$#

    while [ $1 != $DEST ]; do
        SRC=$1

        for IP in `cat /opt/ankit/configs/machine.configs`; do
            echo -en "$IP"
            echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n"
        done

        shift || break
    done
}

hello $*

Вместо того, чтобы передавать только два параметра в функцию hello (), мы передадим все аргументы, полученные сценарием.

Внутри функции hello () мы сначала присваиваем последний аргумент переменной DEST. Затем мы перебираем все аргументы, назначая каждый из них SRC, и запускаем любые команды, которые хотим, используя аргументы SRC и DEST. Обратите внимание, что вы можете захотеть поставить кавычки вокруг $ SRC и $ DEST, если они содержат пробелы. Мы прекращаем цикл, когда SRC совпадает с DEST, потому что это означает, что мы указали последний аргумент (пункт назначения).

1 голос
/ 03 ноября 2008

ОК, это похоже на то, что вы хотите:

#!/bin/bash

hello() {

  SRC=$1
  DEST=$2

   while read IP ; do
     for FILE in $SRC; do
       echo -e "$IP"
       echo -e "\tARG1=$FILE ARG2=$DEST\n"
      done
   done < /tmp/machine.configs
 }

 hello "$1" $2
  1. Вам по-прежнему необходимо экранировать символы подстановки при запуске сценария
  2. Двойные кавычки необходимы при вызове функции hello, в противном случае сам факт вычисления $1 приводит к расширению подстановочного знака, но мы не хотим, чтобы это происходило до тех пор, пока $SRC не будет назначено в функция
1 голос
/ 03 ноября 2008

Вам также не хватает окончательного «готово» для закрытия внешнего цикла for.

0 голосов
/ 15 апреля 2012

Ты бежишь

./test.sh /home/dev/Examples/*.pdf /ankit_test/as 

и ваша интерактивная оболочка расширяет шаблон до того, как сценарий его получит. Вам просто нужно указать первый аргумент при запуске, как в

./test.sh "/home/dev/Examples/*.pdf" /ankit_test/as

и затем в вашем скрипте заключите в кавычки "$ SRC" в любом месте, где вы буквально хотите, чтобы вещи с подстановочными знаками (т. Е. Когда вы делаете echo $SRC, вместо этого используйте echo "$SRC"), и оставьте его без кавычек, когда вы хотите, чтобы подстановочные знаки были расширены , По сути, всегда помещайте кавычки вокруг вещей, которые могут содержать метасимволы оболочки, если только вы не хотите, чтобы метасимволы интерпретировались. :)

0 голосов
/ 03 ноября 2008

Нет необходимости создавать оболочку для просмотра переменной $?, вы можете оценить ее напрямую.

Это должно быть просто:

if [ $? -eq 0 ]; then
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...