подстановка переменной sed с использованием строки - PullRequest
0 голосов
/ 29 мая 2019

Как передать аргумент в sed без входных файлов. Sed находится в одинарной кавычке, и в нем уже есть труба.

git filter-branch -f --index-filter \
      'git ls-files -s | sed -i "s-\t\"*-&dirname/-" |
                GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                git update-index --index-info &&
       mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

Приведенный выше код работает нормально, если dirname жестко запрограммирован. Но мне нужно передать dirname из аргументов командной строки в скрипт. Я стараюсь, как показано ниже, но не повезло.

 'set subdir=$folder;git ls-files -s | sed -i "s-\t\"*-&$subdir/-" |

sed говорит, что входной файл отсутствует. Я не могу напрямую передать входной файл в sed. Я вижу ошибку, как показано ниже.

Rewrite 9c86de42b7f3228e3d45a278c8caf7e24c8e55cf (1/2) (0 seconds passed, remaining 0 predicted)
sed: no input files

Ответы [ 2 ]

2 голосов
/ 29 мая 2019

У вас есть два варианта здесь.Вы можете либо оценить $subdir, чтобы создать фиксированную команду sed, которую вы затем установите в качестве фильтра;или вы можете оценить переменную во фрагменте оболочки, которую вызовет git filter-branch.

Чтобы понять последнее, поймите, что ваша строка --index-filter становится обычной переменной оболочки :

--index-filter)
    filter_index="$OPTARG"
;;

, который затем передается eval:

eval "$filter_index" < /dev/null ||
    die "index filter failed: $filter_index"

eval означает, что выражение в $filter_index, заданное из аргумента --index-filter, имеет доступ ко всем переменным и функциям оболочки в сценарии ветки фильтра .К сожалению, ни одна из ее приватных переменных не содержит нужного вам выражения, но вы можете получить доступ к переменным environment , что означает, что вы можете поместить значение в переменную окружения.Другими словами, вы можете указать subdir=<whatever> в качестве окружения для вашего исходного выражения.

В любом случае, когда bk2204 ответил , вам необходимо удалить -i вариант.Кроме того, некоторые версии sed не принимают \t в качестве символа табуляции (вероятно, ваша принимает, просто имейте это в виду).

Чтобы расширить переменную ранее, просто сделайте это.Например:

... --index-filter \
    'git ls-files -s | sed "s-\t\"*-&'$folder'/-" | ...

(я удалил -i здесь сам).Обратите внимание, как это выходит из одинарных кавычек, расширяет $folder, а затем снова вводит одинарные кавычки.Если $folder может содержать пробел, обязательно используйте двойные кавычки, расширяя его здесь:

... --index-filter \
    'git ls-files -s | sed "s-\t\"*-&'"$folder"'/-" | ...

Вложенность кавычек здесь довольно сложная: вещи внутри одинарных кавычек представляют собой одну большую строку, при условиив качестве аргумента, который устанавливает переменную $filter_index внутри скрипта filter-branch.eval запускает его через второй проход оценки, разбивается на конвейер (git ls-files, передается по каналу sed, передается по каналу git update-index) и запускается несколько различных команд, каждая из которых перенаправляет свой stdin на/dev/null.

2 голосов
/ 29 мая 2019

Вы используете sed -i, который редактирует свои аргументы командной строки (которые являются именами файлов) на месте.Однако вы читаете из стандартного ввода и не предоставили никаких аргументов командной строки.Если вы хотите просто отфильтровать стандартный ввод, как это, пропустите -i из вашей команды sed.

...