Polecenie zmiany znaczenia ciągu w bash

99

Potrzebuję polecenia bash, które skonwertuje ciąg znaków na coś, z czym zostanie usunięty. Oto przykład:

echo "hello\world" | escape | someprog

Gdzie komenda ucieczka czyni "hello\world"się "hello\\\world". Następnie jakiśprog może używać "hello\\world"zgodnie z oczekiwaniami. Oczywiście jest to uproszczony przykład tego, co naprawdę będę robić.

Użytkownik1
źródło
5
Jaka jest natura ucieczki? Innymi słowy, przed jakimi postaciami trzeba uciec? Szukasz wyjścia w stylu C ++ (gdzie tabulatory są zastępowane przez \ t, znaki nowej linii na \ n, cudzysłowy na \ "itp.)? Trudno jest pomóc bez dobrze zdefiniowanego problemu.
Michael Aaron Safyan
2
możliwy duplikat echa, które wymyka się argumentom
P Shved
To pytanie może oznaczać dowolną z kilkunastu różnych rzeczy. Zamiast nas zgadywać, pomogłoby, gdybyś dokładnie określił, jakiego rodzaju ucieczki szukasz.
Don Hatch
1
Pytanie dotyczyło używania znaku \\ dla \. Jest zaakceptowana odpowiedź.
Użytkownik1

Odpowiedzi:

155

W Bash:

printf "%q" "hello\world" | someprog

na przykład:

printf "%q" "hello\world"
hello\\world

Można to również wykorzystać za pomocą zmiennych:

printf -v var "%q\n" "hello\world"
echo "$var"
hello\\world
Wstrzymano do odwołania.
źródło
6
Pamiętaj, %qbył zepsuty przez ponad dekadę, aż do około 2012 roku. Miał problemy z ~. Istnieją również przenośne jednokładkowe sedes stackoverflow.com/a/20053121/1073695
Jo So
1
sed jest rzeczywiście lepszy, ponieważ może też uciec przed znakami dolara
2016
2
@untore: a='abc$def":'; printf '%q\n' "$a"daje w wyniku abc\$def\":(znak dolara jest usuwany ). To jest Bash 4.3 (ten sam wynik uzyskałem w Bash 3.2). Jakiej wersji używasz?
Wstrzymano do odwołania.
3
aby uniknąć znaku dolara, użyj zamiast tego pojedynczych cudzysłowów, np .:printf "%q" 'he$l&lo\world'
LeandroCR
bash printf '%q\n' textcytuje tekst w bashformacie (i dla bieżących ustawień regionalnych), więc zadziałałoby to tylko w przypadku OP, gdyby ich someprogskładnia cytowania była dokładnie taka sama, jak bashjest to wysoce nieprawdopodobne.
Stephane Chazelas
9

Pure Bash, użyj podstawiania parametrów:

string="Hello\ world"
echo ${string//\\/\\\\} | someprog
Fritz G. Mehner
źródło
1
w ten sposób "hello world" nie jest uciekane do "hello \ world" - podejście printf w zaakceptowanej odpowiedzi to robi.
vchrizz
1
Poza tym „% q” nie zmienia znaku „/” jak w „25.03.2017”, którego potrzebowałem, aby przejść do „03 \ / 25 \ / 2017” (tak, aby mógł znajdować się w zwykłym rozdzielanym „/” wyrażenie).
wrlee
0

Możesz użyć perla do zamiany różnych znaków, na przykład:

$ echo "Hello\ world" | perl -pe 's/\\/\\\\/g'
Hello\\ world

W zależności od charakteru ucieczki, możesz połączyć wiele wywołań, aby uciec odpowiednim postaciom.

Michael Aaron Safyan
źródło
1
Dlaczego nie sed? $ echo "hello \ world" | sed 's / \\ / \\\\ /'
Space
1
@Octopus, to również poprawna opcja. Tak się składa, że ​​czuję się bardziej komfortowo z perlem, ale tak, to też działa.
Michael Aaron Safyan