Evadarea atât a bară oblică înainte, cât și a bară oblică înapoi cu sed (Unix, Bash, Sed)

James a intrebat.

Am următorul șir de caractere: /tmp/test/folder1/test.txt

Doresc să folosesc sed pentru a înlocui / pentru / – de exemplu:

/tmp/test/folder1/test.txt

Așa că emit:

echo "/tmp/test/folder1/test.txt" | sed "s///\\//g"

Deși se întoarce:

sed: -e expresia #1, char 9: unknown option to `s’.

Scap slash-ul și backslash-ul – așa că nu sunt sigur unde am greșit aici.

Comentarii

  • Doriți să înlocuiți / pentru / (deci înlocuiți toate / cu /) sau doriți să înlocuiți / pentru / (înlocuiți toate / cu /)? –  > Por terdon.
  • @James ai putea folosi un delimitator diferit în comanda sed, cum ar fi sed ‘s:something:toSomethingElse:’ –  > Por αғsнιη.
3 răspunsuri
jimmij

Trebuie să scăpați (cu backslash ) toate slash-urile substituite / și toate backslash-urile separat, deci:

$ echo "/tmp/test/folder1/test.txt" | sed 's///\//g'
/tmp/test/folder1/test.txt

dar este mai degrabă ilizibil.

Cu toate acestea, sed permite utilizarea a aproape orice caracter ca separator în loc de /, acest lucru este util mai ales atunci când se dorește să se înlocuiască slash-ul / în sine, ca în cazul dumneavoastră, astfel încât, folosind de exemplu punct și virgulă ; ca separator, comanda ar deveni mai simplă:

echo "/tmp/test/folder1/test.txt" | sed 's;/;\/;g'

Alte cazuri:

  • Dacă se dorește să se păstreze slash ca separator și să se utilizeze ghilimele duble, atunci toate backslash-urile scăpate trebuie să fie scăpate încă o dată pentru a păstra valorile lor literale:

    echo "/tmp/test/folder1/test.txt" | sed "s///\\//g"
    
  • dacă nu se doresc ghilimele deloc, atunci este necesară încă o backslash:

    echo "/tmp/test/folder1/test.txt" | sed s/\//\\\//g
    

Comentarii

  • Mulțumesc Am observat, de asemenea, că utilizați ghilimele simple – deoarece presupun că ghilimelele duble nu ar păstra valoarea literală a caracterului „
    . –  > Por James.
  • @James da, tot ceea ce se află între ghilimele simple este tratat literal de către shell și este transmis către sed. În interiorul ghilimelelor duble, unele caractere sunt extinse și chiar expresii întregi pot fi evaluate de shell. –  > Por jimmij.
  • @James Am adăugat exemple cu ghilimele diferite la răspuns, poate fi util. –  > Por jimmij.
Jeff Schaller

Sau, dacă valoarea se află într-o variabilă shell (bash):

var=/tmp/test/folder1/test.txt
$ echo "${var////\/}"
/tmp/test/folder1/test.txt

Prima // start extinderea parametrului, care spune să înlocuiască toate meciurile cu înlocuitorul. Următorul / este scăpat / pentru a se potrivi, iar \/ este un scăpat urmat de un scăpat / ca înlocuitor.

Comentarii

  • Se pot utiliza și alte forme de citare (în afară de backslash). Încercați echo "${var//'/'/'/'}" (începând cu bash 4.3) –  > Por Isaac.
Isaac

Soluția finală va fi aceasta:

$ sed 's:/:\/:g'  <<<"$str"
/tmp/test/folder1/test.txt

Dar pentru a explica cum se ajunge acolo:
Da, îți lipsea o backslash:

$ str='/tmp/test/folder1/test.txt'
$ sed "s///\\//g" <<<"$str"
/tmp/test/folder1/test.txt

Sper că un spațiu va clarifica totul:

$ sed "s///\\ //g"  <<<"$str"
 /tmp /test /folder1 /test.txt

Dar, dacă ai schimba delimitatorul sed în : (de exemplu):

$  sed "s:/:\\/:g"  <<<"$str"
/tmp/test/folder1/test.txt

Dar asta nu e strict corect, pentru că (acum nu mai e special) / nu mai are nevoie de spațiere:

$ sed "s:/:\\/:g"  <<<"$str"
/tmp/test/folder1/test.txt

Și, dacă ați folosi ghilimele simple în loc de ghilimele duble, shell-ul nu va schimba ghilimelele duble. \ în unul singur, deci mai puțin va fi corect:

$ sed 's:/:\/:g'  <<<"$str"
/tmp/test/folder1/test.txt

Ceea ce este destul de curat.

Tags:,