Jak zamienić cudzysłowy w pliku na sed?

10

Mam plik zawierający wiele wierszy xml. Chciałbym zastąpić niektóre części pliku. Niektóre części pliku zawierają znaki cudzysłowu ( "), które chciałbym zastąpić. Próbowałem uciec od znaku cudzysłowu \, ale nie sądzę, że działa to na podstawie wyniku mojego pliku.

Oto przykład jednego z moich poleceń sed:

sed -e "s/\"text\"/'text'/ig" file.xml > temp.tmp

Czy w ten sposób unikasz cudzysłowów w poleceniu sed, czy robię coś złego?

jbranchaud
źródło
2
Twoje polecenie wygląda prawo do wymiany "text"ze 'text'. Oczywiście nic to nie da "othertext". Pokaż kilka wierszy wejściowych, odpowiadające im niepożądane wyjście i wyjaśnij, jakiego wyjścia chcesz.
Gilles „SO- przestań być zły”
Czy więc \"prawidłowy sposób na unikanie cudzysłowów w poleceniu sed?
jbranchaud
4
Nie dla sed: sed nie potrzebuje ucieczki ". Ale twoje polecenie powłoki używa podwójnego cudzysłowu i \"jest tam poprawne. sedProgram widzi s/"text"/'text'/igjako argument -e.
Gilles „SO- przestań być zły”
@Gilles Co ze spacjami? Czy sed rozumie i szanuje białe przestrzenie? Na przykład, jeśli moje polecenie zawierałoby: s/\"text\" /'text'/igCzy znajdzie tylko "text" po spacji po nim?
jbranchaud
3
Spacje muszą dokładnie pasować. Zamiast kontynuować ten dialog, zalecam opublikowanie przykładowych danych wejściowych i odpowiadających im pożądanych wyników (i być może wyjaśnienie, dlaczego trzeba zmienić cytowanie). Nie jest nawet jasne, czy sedjest to odpowiednie narzędzie do pracy, może potrzebujesz parsera XML.
Gilles „SO- przestań być zły”

Odpowiedzi:

11

Dwie wskazówki:

  1. Nie można uciec przed pojedynczym cytatem w ciągu cytowanym pojedynczymi cudzysłowami. Musisz zamknąć wycenę, dodać wycenę, a następnie ponownie otworzyć wycenę. To znaczy 'foo'\''bar':, który rozkłada się na:

    • 'foo'        zacytowany foo
    • \'             uciekł '
    • 'bar'        zacytowany bar

    poddający się foo'bar.

  2. (opcjonalnie) Nie musisz używać /w sed. Uważam, że używanie /i \w tym samym wyrażeniu sed utrudnia przeczytać.

Na przykład, aby usunąć cytaty z tego pliku:

$ cat /tmp/f
aaa"bbb"'ccc'aaa

Biorąc pod uwagę moje dwie powyższe wskazówki, możesz użyć polecenia, aby usunąć zarówno podwójne, jak i pojedyncze cudzysłowy:

$ sed -e 's|["'\'']||g'  /tmp/f

W oparciu o moją pierwszą wskazówkę, powłoka redukuje drugi argument sed (tj. Ciąg po -e) do s|["']||gi przekazuje ten ciąg do sed. Na podstawie mojej drugiej wskazówki sed traktuje to tak samo jak s/['"]//g. To znaczy

usuń wszystkie znaki pasujące do jednego 'lub "   (tj. zamień je na nic)

Prawdopodobnie potrzebujesz czegoś bardziej złożonego niż to, co chcesz, ale to dopiero początek.

Yves Junqueira
źródło
1
Aby dokładniej wskazać drugą wskazówkę: możesz użyć dowolnej postaci zamiast / podczas używania poleceń s i y, być może między innymi. Podczas używania wyrażeń regularnych z innymi poleceniami sed, pierwszy separator (jeśli używasz alternatywy dla /) musi być poprzedzony znakami ucieczki. Preferowany separator również musi być poprzedzony znakiem ucieczki, jeśli próbujesz dopasować go w wyrażeniu regularnym.
Eli Heady
Trudno mieszać pojedyncze cytaty i podwójne cytaty bez bałaganu. Niektórym łatwiej jest czytać, jeśli cytujesz pojedyncze cytaty, umieszczając je w podwójnych cudzysłowach, zamiast uciec od nich. Zamiast tego 'foo'\''bar'moglibyśmy użyć 'foo'"'"'bar'.
Scott
1

Mam port narzędzi uniksowych dla systemu Windows, więc polecenia wyglądają nieco inaczej, ale miałem plik csv z przecinkami i znakami cudzysłowu. Używając tego wątku jako przewodnika, mogłem usunąć cytaty za pomocą tego polecenia:

c:\Temp> cat report.csv | sed "s/\,/\ /g" | sed "s/[""]//g"
JaimeR744
źródło
dzięki! utknąłem na tym!
sendbits