Как обрабатывать переменные, которые содержат «;»? - PullRequest
1 голос
/ 13 сентября 2011

У меня есть файл конфигурации, который содержит такие строки, как "hallo; welt;"и я хочу сделать grep для этого файла.Всякий раз, когда я пытаюсь что-то вроде grep "$1;$2" my.config или echo "$1;$2 четной строки = "$ 1; $ 2", мой сценарий завершается с чем-то вроде:

: команда не найдена95: строка 155: = hallo ...

Как я могу сказать Bash игнорировать;при оценке блоков "..."?

РЕДАКТИРОВАТЬ: пример моего кода.

# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)

# do some stuff on the permissions

# replace old line with new line
nline="$1;$2;$reads;$writes;$admins"
sed -i "s/$line/$nline/g" $TEMPPERM

мой скрипт должен называться так: sh script "table" "ab *.>"

РЕДАКТИРОВАТЬ: другой, более простой пример

$test=$(grep "$1;$2;" temp.authorization.config)

временный файл:

table;pattern;read;write;stuff

шаблон таблицы call sh test.sh приводит к: : command not foundtable;pattern;read;write;stuff

Ответы [ 4 ]

4 голосов
/ 13 сентября 2011

Не используйте $ в левой части присваивания в bash - если вы это сделаете, оно заменит текущее значение переменной, а не присваивает ее. То есть используйте:

test=$(grep "$1;$2;" temp.authorization.config)

вместо:

$test=$(grep "$1;$2;" temp.authorization.config)

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

reads=$(echo "$line" | cut -d';' -f3)

вместо:

reads=$(echo $line | cut -d';' -f3)

Это не имеет значения для точек с запятой, но имеет значение для пробелов, подстановочных знаков и некоторых других вещей.

3 голосов
/ 13 сентября 2011

A ; внутри кавычек не имеет никакого значения для bash.Однако, если $ 1 содержит саму двойную кавычку, вы получите

grep "something";$2"

, который будет проанализирован bash как две отдельные команды:

grep "something"   ;     other"
^---command 1----^    ^----command 2---^

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

1 голос
/ 13 сентября 2011

Контрпример:

$ cat file.txt
hello;welt;
hello;world;
hell;welt;  
$ cat xx.sh
grep "$1;$2" file.txt
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
$

Вы еще не классифицировали свою проблему точно.


Если вы пытаетесь присвоить результат grep переменной (как и я) твой пример ломается.

Пожалуйста, покажи, что ты имеешь в виду.Используя тот же файл данных, что и раньше, и выполняя задание, я получаю следующий вывод:

$ cat xx.sh
grep "$1;$2" file.txt
output=$(grep "$1;$2" file.txt)
echo "$output"
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
++ grep 'hello;welt' file.txt
+ output='hello;welt;'
+ echo 'hello;welt;'
hello;welt;
$

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


Я вижуВы предоставили пример кода:

# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)

Неверная строка $line=$(grep ...).Вы должны опустить $ до line.Хотя это синтаксически правильно, это означает «присваивать переменной, имя которой хранится в $line результат команды grep».Это вряд ли то, что вы имели в виду.Это иногда полезно.Тем не менее, эти случаи редки и далеко, и только для людей, которые знают, что они делают, и которые могут точно документировать, что они делают.

В целях безопасности, если ничего больше, я бы также приложил $line значений в двойных кавычках в строках echo.Это может не быть строго необходимым, но это простое защитное программирование.

Изменения приводят к:

# find entry
line=$(grep "$1;$2;" $PERMISSIONSFILE)
# split line
reads=$( echo "$line" | cut -d';' -f3)
writes=$(echo "$line" | cut -d';' -f4)
admins=$(echo "$line" | cut -d';' -f5)

Остальная часть вашего сценария была в порядке.

0 голосов
/ 13 сентября 2011

Похоже, вы пытаетесь прочитать файл, разделенный точкой с запятой, определить строку, начинающуюся с 'table; pattern;' где table - указанная вами строка, а pettern - регулярное выражение, которое grep поймет. После определения строки вы хотите заменить 3-е, 4-е и 5-е поля другими данными и записать обновленную строку обратно в файл.

Это звучит правильно?

Если это так, попробуйте этот код

#!/bin/bash

in_table="$1"
in_pattern="$2"
file="$3"

while IFS=';' read -r -d$'\n' tuple pattern reads writes admins ; do
    line=$(cut -d: -f1<<<"$tuple")
    table=$(cut -d: -f2<<<"$tuple")

    # do some stuff with the variables
    # e.g., update the values
    reads=1
    writes=2
    admins=12345

    # replace the old line with the new line
    sed -i'' -n $line'{i\
'"$table;$pattern;$reads;$writes;$admins"'
;d;}' "$file"
done < <(grep -n '^'"${in_table}"';'"${in_pattern}"';' "${file}")

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

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