2010-03-03 9 views
29

Jestem ciekawa, dlaczego sed potrzebuje 3 \ tylko po to, żeby rozpoznać jedną? Rozumiem, że potrzebuje 2, ale 3 nie.Dlaczego sed wymaga 3 backslashes dla zwykłego backslash?

EDIT: oto przykład na moim komputerze z systemem Windows za pomocą Cygwin:

echo "sample_input\whatever" | sed "s/\\\/\//" 

Gdybym nie dodać 3 backslashy, otrzymuję

sed: -e expression #1, char 7: unterminated s' command 
+0

pokaż, co masz – ghostdog74

+0

Nie ma. Pokaż nam, dlaczego tak uważasz. –

+0

to twoja powłoka zużywająca dodatkowy poziom backslashingu? – p00ya

Odpowiedz

31

Udało mi się odtworzyć to zachowanie za pomocą Vista i Cygwin 1.7.0.

  • Dwa backslashe produkować błąd
  • albo trzy lub cztery backslashe pracować
  • Pięć daje ten sam błąd

Dwa backslashe stać pojedynczy ukośnik w powłoce, która następnie w sed ucieka przednim ukośnikiem, który jest środkowym ogranicznikiem.

\\/ -> \/ (which makes the forward slash a regular character instead of a delimiter) 

trzy z nich: pierwsze dwie się jeden w zbiorniku, który następnie uciec trzeci w sed

\\\/ -> \\/ 

czwarty: Każda para staje się pojedyncze te w powłoce następnie pierwszy otrzymanego jeden ucieczki drugi w sed

\\\\/ -> \\/ 

EDIT:

Och, zapomniałem powiedzieć, że zarówno pojedyncze cytaty, jak i podwójne cudzysłowy działały tak samo dla mnie (cmd.exe nie czyni rozróżnienia, że ​​Bash, i inni, czyni).

+0

Ale 's/\\ [0-9] * //' wydaje się poprawne, jeśli znak po ukośniku odwrotnym nie jest ukośnikiem – Timo

4

Proszę pokazać przykład, czego w przyszłości. w sed, że chcesz zastąpić „\” z potoku (|), na przykład

$ cat file 
asklfja \ asf 

$ sed 's/\\/|/g' file 
asklfja | asf 

$ sed 's%\\%|%g' file #using different delimiter 
asklfja | asf 

wystarczy uciec raz.

Edycja: Dla przykładu @ OP, ponieważ używasz cmd.exe, a nie bash/ksh, cmd.exe nie lubi pojedynczych cudzysłowów. Nie mogę przedstawić twojego scenariusza. To działa na moim GNU sed na okna stosując 2 tnie

np

C:\test>echo "sample_input\whatever" | sed "s/\\/\//" 
"sample_input/whatever" 
+1

@ ghostdog74, wysłałem przykład: – Geo

+0

@geo, zobacz moją edycję – ghostdog74

+0

Nie używam bash, ghostdog74, i z pojedynczymi cytatami, pojawia się ten sam błąd. – Geo

0

Chyba, zakładasz \\\n lub \\\t jak trzy backslashy tam, ale faktycznie, jego 2 backslashy i kolejne wzory

backslash   \\ 
    newline   \n 
    tab    \t 

również, może potrzebować uciec, ponieważ w s/.../, używa się do otwierania i zamykania części.

tak /\\\/\// byłoby \\ + \/ + \/ według zaktualizowanego przykład

+0

Podoba mi się twoja metoda w wyjaśnianiu, czy mógłbyś spojrzeć na to i spróbować odpowiedzieć? https://superuser.com/questio ns/1249497/sed-needs-n-to-append-new-line? noredirect = 1 # comment1834908_1249497 –

8

Twój powłoki (bash) prawdopodobnie robi własną ucieczce i to mylące ciebie. Można użyć polecenia echo, aby zobaczyć, co jest przekazywane, czy łatwo jest napisać program niestandardowy (zwykle o nazwie „showargs” lub podobny):

 
$ echo "s/\\\/\//" 
s/\\/\// 
$ echo "s/\\/\//" 
s/\/\// 

można również używać apostrofów, które są traktowane odmiennie w grzmotnąć.

+0

Używam "cmd.exe" systemu Windows, a nie bash. – Geo

+0

@Geo: Domyślam się bash, ponieważ wspomniałeś o cygwin, ale inne muszle też uciekają. –

1

W mojej wersji CYGWIN działa jak oryginalny plakat, ale działa inaczej (normalnie), jeśli używam pojedynczych cudzysłowów.

 
$ echo "sample_input\whatever" | sed 's/\\/\//' 
sample_input/whatever 
 
$ echo "sample_input\whatever" | sed "s/\\/\//" 
sed: -e expression #1, char 7: unterminated `s' command 

Hmmm ..

0

Wymiana jeden backslash z dwóch na moim Cygwin wymaga tego wyrażenia:

sed -e "s | \\ | \\\\ | g"

5

Jest to spowodowane podwójnie cytowaną regułą parsowania ciągów w postaci sh.

Posix określa, w jaki sposób sh analizuje ciągi o podwójnych cudzysłowach.

Odwrotny ukośnik zachowuje swoje szczególne znaczenie jako znak ucieczki (patrz Ucieczka znaku (backslash)) tylko wtedy, gdy następuje przez jeden z następujących znaków kiedy uznać specjalny: $ `" \

W inne słowa, sh lewusuje lewy ukośnik, za którym występują znaki inne niż $ '".

Tak więc, jeśli sh spełnia podwójnie cytowany ciąg sed "s/\\\/\//", sh analizuje go w następujący sposób.

  1. Pierwsze dwa \\ zmieniono na . Ponieważ pierwszy \ następuje po drugim \.
  2. Trzeci i czwarty \ jest nadal pozostawiony w łańcuchu. Ponieważ po obydwu występuje /, co nie jest specjalną cechą podwójnego cudzysłowu.

Po pasring, sh przechodzi ciąg s/\\/\// do sed, który zastępuje pierwszy wystąpienie \ do /.

Z tego samego rozumowania, gdy sh spełnia ciąg, "sed s/\\\\/\//", sh przechodzi /\\/\// do sed, który zastępuje także pierwsze wystąpienie \ do /.

Powiązane problemy