Я пытаюсь избежать предоставленной пользователем строки поиска, которая может содержать любой произвольный символ, и передать его в sed, но не могу понять, как сделать его безопасным для использования в sed. В sed мы делаем s/search/replace/
, и я хочу искать точно символы в строке поиска, не интерпретируя их с помощью sed (например, '/' в 'my / path' не закрывает выражение sed).
Я прочитал этот связанный вопрос о том, как избежать термина replace . Я бы подумал, что вы сделаете то же самое с поиском , но, очевидно, не потому, что sed жалуется.
Вот пример программы, которая создает файл с именем «my_searches». Затем он читает каждую строку этого файла и выполняет поиск и замену с использованием sed.
#!/bin/bash
# The contents of this heredoc will be the lines of our file.
read -d '' SAMPLES << 'EOF'
/usr/include
P@$$W0RD$?
"I didn't", said Jane O'Brien.
`ls -l`
~!@#$%^&*()_+-=:'}{[]/.,`"\|
EOF
echo "$SAMPLES" > my_searches
# Now for each line in the file, do some search and replace
while read line
do
echo "------===[ BEGIN $line ]===------"
# Escape every character in $line (e.g., ab/c becomes \a\b\/\c). I got
# this solution from the accepted answer in the linked SO question.
ES=$(echo "$line" | awk '{gsub(".", "\\\\&");print}')
# Search for the line we read from the file and replace it with
# the text "replaced"
sed 's/'"$ES"'/replaced/' < my_searches # Does not work
# Search for the text "Jane" and replace it with the line we read.
sed 's/Jane/'"$ES"'/' < my_searches # Works
# Search for the line we read and replace it with itself.
sed 's/'"$ES"'/'"$ES"'/' < my_searches # Does not work
echo "------===[ END ]===------"
echo
done < my_searches
Когда вы запускаете программу, вы получаете sed: xregcomp: Invalid content of \{\}
для последней строки файла, когда он используется как термин «поиск», но не как термин «замена». Я отметил строки, которые дают эту ошибку с # Does not work
выше.
------===[ BEGIN ~!@#$%^&*()_+-=:'}{[]/.,`"| ]===------
sed: xregcomp: Invalid content of \{\}
------===[ END ]===------
Если вы не экранируете символы в $line
(т.е. sed 's/'"$line"'/replaced/' < my_searches
), вы получите эту ошибку вместо этого, потому что sed пытается интерпретировать различные символы:
------===[ BEGIN ~!@#$%^&*()_+-=:'}{[]/.,`"| ]===------
sed: bad format in substitution expression
sed: No previous regexp.
------===[ END ]===------
Итак, как мне избежать термина поиска для sed, чтобы пользователь мог предоставить любой произвольный текст для поиска? Или, точнее, чем можно заменить строку ES=
в моем коде, чтобы команда sed работала с произвольным текстом из файла?
Я использую sed, потому что я ограничен набором утилит, включенных в busybox . Хотя я могу использовать другой метод (например, программу на C), было бы неплохо знать наверняка, есть ли решение этой проблемы.