2009-04-18 15 views
5

Piszę skrypt powłoki i chcę uciec ciąg znaków. Czy istnieje jakiś sposób, aby przekształcić to:Escape a string

I'm happy. 
You're sad. 

do

I\'m happy.\nYou\'re sad. 

Jestem całkiem pewien, że istnieje jakaś kombinacja sed/awk że robi to ....

Dzięki

Odpowiedz

0

spróbuj

sed 's/\\ /\\n/g' | sed 's/\\'/\\\'/g' 

Pewnie zawiodłem kilka tutaj \. Najlepszym sposobem jest wypróbowanie tego samemu.

+0

Nie trzeba uruchamiać 2 sed poleceń, można uruchomić wiele podstawienia wewnątrz jednej sed pw. Myślę, że każdy z nich jest zakończony znakiem ";" znak, chociaż jeśli to nie zadziała, to po prostu umieść 2 linie w pliku i użyj "sed -f " – slacy

+0

@slacy: sed -e 's/foo/bar/g' -e 's/baz/qux/g ' –

+0

tego nie wiedział. dzięki! – Chaitan

0

Umożliwia to zastąpienie ' przez \'.

echo "I'm happy. You're sad" | sed "s/'/\\\'/g" 

Czy na pewno chcesz zastąpić przestrzeń między "szczęśliwymi". i "Jesteś" z \n? \n to znak nowej linii, ale pierwotna linia nie ma tam nowej linii.

+0

Tak, chce \ n, on po prostu zepsuł swój znacznik SO (Eddie naprawił to) – derobert

0

Myślę, że to robi to, o co prosisz. Sekwencjonowanie operacji w poleceniu sed jest dość krytyczne. Zauważ, że ta zajmuje się również ukośniki (jak również pojedynczych cudzysłowach) w ciągu (mój szybka PS1 jest Osiris JL:):

Osiris JL: cat zzz 
xxx="I'm happy. 
You're sad." 
yyy=$(echo "$xxx" | sed 's/[\'\'']/\\&/g;s/$/\\n/;$s/\\n$//') 
echo "$xxx" 
echo $xxx 
echo "$yyy" 
echo $yyy 
#eval echo $yyy 
#eval echo "$yyy" 
Osiris JL: sh zzz 
I'm happy. 
You're sad. 
I'm happy. You're sad. 
I\'m happy.\n 
You\'re sad. 
I\'m happy.\n You\'re sad. 
Osiris JL: 
0

Oto moje rozwiązanie używając awk:

$ awk '{$1=$1}1' FS=\' OFS="\\\'" ORS='\\n' <<< "I'm happy. 
You're sad." 

Wynika to w wyjście

I\'m happy.\nYou\'re sad.\n 

Objaśnienie:

ja ustawić pole Separator (FS) do ' (uciekając go za shell jako \') i Wyjście Pole Separator (OFS) do \' (zawinięte w "..." do ucieczki ' dla shell i ucieczki \ dwukrotnie , raz dla shell i drugi raz dla awk, jako "\\\'"). Bez dalszych opcji Record Separator (RS) jest znak nowej linii, ale ustawić Wyjście Record Separator (ORS) do \n (znowu uciekając \ dla awk jak \\n).

Teraz pozostaje tylko powiedzieć awk zrobić to ponownie obliczać każdy rekord (poprzez ustawienie $1 do $1, nic się nie zmienia, ale awk myśli rekord zmieniło, skutecznie zastępując FS przez OFS und zatem każdy ' przez \') i wydrukuj każdy rekord (tak wygląda wzór 1: 1 jest prawdziwy dla wszystkich rekordów i ponieważ nie podano żadnej akcji, wykonywane jest standardowe działanie {print $0}), skutecznie zastępując RS przez ORS, a zatem każdy nowy wiersz przez \n.

1

Możesz użyć zwykłego Basha do tego (patrz http://tldp.org/LDP/abs/html/string-manipulation.html).

Coś jak:

#!/bin/bash 
X="I'm happy. 
You're sad." 
echo "========== BEFORE ==========" 
echo "${X}" 
echo "========== AFTER ===========" 
X="${X//\'/\\\'}" 
X="${X//$'\n'/\\n}" 
echo "${X}" 
echo "============================" 

spowoduje wyjście:

========== BEFORE ========== 
I'm happy. You're sad. 
========== AFTER =========== 
I\'m happy.\nYou\'re sad. 
============================ 
+0

Czy używasz bash lub innej alternatywy (jak na przykład "kreska" w dystrybucji Ubuntu)? Sprawdź, uruchamiając: #> ls -la/bin/bash jeśli jest to dowiązanie symboliczne, prawdopodobnie NIE używasz BASH. –

+0

To była tylko próbka, która unikała oddzielania procesów w podpowłoce, jak pokazuje większość proponowanych rozwiązań. Zmieniono przykładowy kod, aby wykonać to, o co prosiłem w nagłówku tematu. Teraz to robi. –

+0

Teraz to działa również dla mnie. Usuwam moje stare komentarze, ponieważ nie dodają niczego oprócz pomieszania do aktualnego anwsera. – mschilli