2016-08-26 3 views
2

Я хочу заменить местозаполнитель во всех файлах под каталогом со строкой, которая генерируется с пользовательского ввода. Этот вход может содержать / : . ~Использование ~ в Perl поиск и замена

Я выбрал Perl для выполнения этой задачи.

perl -p -i -e "s/__MY_PLACEHOLDER__/$user_input/g" `find my_dir -type f -print0 | xargs -0` 

Теперь ~ является зарезервированным символом в Perl. Как я могу избежать ~ в $user_input? \~ не работает.

+0

Я собирался предложить [этот вопрос] (http://stackoverflow.com/q/7970702/176646) как дубликат, но мне просто не нравится принятый ответ. Вы на самом деле объединили два общих (но хороших!) Вопроса: 1) как передать переменную оболочки Perl? и 2) как избежать специальных символов в регулярном выражении? Я не могу найти подходящий вопрос, который обращается к обоим сразу, так что, возможно, это может стать новым каноническим вопросом. – ThisSuitIsBlackNot

+2

Вы всегда должны обертывать однострочники Perl в одинарных кавычках на \ * nix. Слишком просто случайно случайно интерполировать переменную оболочки или вызвать команду истории (например, 'perl -e" s! Foo! Bar! "' Ошибки с '" bash:! Foo! Bar! ": Событие не найдено 'в bash). Вы должны использовать Perl '% ENV' хэш или передать переменные bash в качестве аргументов для Perl-скрипта. Есть несколько приятных сообщений об этом, я постараюсь найти их для вас. – ThisSuitIsBlackNot

+1

Я бы спешил указать, что ваш 'perl' не будет делать то, что вы ожидаете от него, когда' find' находит файлы, содержащие пробелы. –

ответ

9

Фактически, ~ не является особым в литералах с двойной кавычкой, например, с заменой выражения s///. Однако некоторые другие являются особенными. Из четырех символов, которые вы указали, / является специальным, когда / используется как разделитель, как здесь.

Не пытайтесь генерировать Perl-код из оболочки! Используйте одно из следующих действий:

export $user_input 
perl -i -pe's/__MY_PLACEHOLDER__/$ENV{user_input}/g' 

или

USER_INPUT=$user_input perl -i -pe's/__MY_PLACEHOLDER__/$ENV{USER_INPUT}/g' 

или

perl -i -pe' 
    BEGIN { $user_input = shift } 
    s/__MY_PLACEHOLDER__/$user_input/g 
' "$user_input" 

Кстати, вы действительно пропустил точку xargs!

perl ... `find my_dir -type f -print0 | xargs -0` 

ничем не отличается, чем

perl ... `find my_dir -type f` 

То, что вы хотели это

find my_dir -type f -print0 | xargs -0 perl ... 

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

+0

Связано: [Когда требуется 'xargs'?] (Http://unix.stackexchange.com/q/24954/446) – Zaid

Смежные вопросы