Jak sprawić, aby wiersz polecenia systemu Windows traktował pojedynczy cytat tak, jakby był podwójnym cytatem?

6

Mój scenariusz jest prosty - kopiuję próbki skryptów z książki online Mercurial i wklejam je w wierszu polecenia systemu Windows. Problem polega na tym, że próbki w książce używają pojedynczych cudzysłowów. Gdy w wierszu polecenia systemu Windows przekazywany jest ciąg pojedynczego cudzysłowu, ten ostatni nie rozpoznaje, że wszystko między pojedynczymi cudzysłowami należy do jednego ciągu.

Na przykład następujące polecenie:

hg commit -m 'Initial commit'

nie można wkleić tak, jak w wierszu polecenia, ponieważ ten ostatni traktuje 'Initial commit'jako dwa ciągi - 'Initiali commit'. Muszę edytować polecenie po wklejeniu i jest to denerwujące.

Czy można poinstruować wiersz polecenia systemu Windows, aby traktował pojedyncze cudzysłowy podobnie jak podwójne?

EDYTOWAĆ

Po odpowiedzi JdeBP przeprowadziłem trochę badań. Oto podsumowanie:

  • Punkt wejścia Mercurial wygląda tak (jest to program python):

    def run():
        "run the command in sys.argv"
        sys.exit(dispatch(request(sys.argv[1:])))
    
  • Stworzyłem więc mały program python, który naśladuje przetwarzanie wiersza poleceń używane przez mercurial:

    import sys
    print sys.argv[1:]
    
  • Oto dziennik konsoli Unix:

    [hg@Quake ~]$ python 1.py  "1 2 3"
    ['1 2 3']
    [hg@Quake ~]$ python 1.py  '1 2 3'
    ['1 2 3']
    [hg@Quake ~]$ python 1.py  1 2 3
    ['1', '2', '3']
    [hg@Quake ~]$
    
  • A oto odpowiedni dziennik konsoli Windows:

    C:\Work>python 1.py  "1 2 3"
    ['1 2 3']
    
    C:\Work>python 1.py  '1 2 3'
    ["'1", '2', "3'"]
    
    C:\Work>python 1.py  1 2 3
    ['1', '2', '3']
    
    C:\Work>
    

Widać wyraźnie, że system Windows nie traktuje pojedynczych cudzysłowów jako podwójnych. I to jest istota mojego pytania.

znak
źródło
2
Albo oznaczyłeś to pytanie przez pomyłkę jako „Windows”, albo bardzo nieto monity poleceń DOS .
JdeBP
Uwaga: Twój program demonstracyjny dodaje pojedyncze cytaty na wyjściu, co być może trochę zaciemnia. Rzeczywiście system Windows n unix traktuje pojedyncze n podwójne cudzysłowy inaczej, patrz mój komentarz w odpowiedzi 2 JdeBP. To powiedziawszy, istnieją dwa sposoby, w jakie programy Windows mogą uzyskać wiersz poleceń (obszar po znaku zachęty) .1) GetCommandLine () 2) argsv. Argsv prawdopodobnie działa, wykonując GetCommandLine, a program, zanim dotrzesz do pierwszego wiersza funkcji głównej, podzieli go na argumenty oparte na tych regułach (w przypadku Ms Visual C) lub na podobnych regułach. msdn.microsoft.com/en-us/library/a1y7w461.aspx
barlop
spróbuj skompilować ten pastebin.com/raw.php?i=4Bq7unGd i ten pastebin.com/raw.php?i=QkhBJWGb Oba w systemie Windows. Spróbuj wywołać je z argumentami i przekonaj się na podstawie wyników, jak traktują argumenty inaczej. Jeden używa GetCommandLine () jeden używa argsv. Sam system Windows nie rozdziela argumentów, nie wytwarza elementów argsv.
barlop

Odpowiedzi:

6

Znaku cudzysłowu nie można zmienić w wierszu polecenia command.com. Możesz jednak użyć programu PowerShell, który przyjmuje zarówno pojedyncze, jak i podwójne cudzysłowy jako znaki cudzysłowu. Działają tak samo jak w powłokach uniksowych. Tzn. Pojedyncze cudzysłowy nie rozszerzają zmiennych, podczas gdy podwójne cudzysłowy będą.

Nadal możesz mieć problemy z cytatami w cytatach. Na przykład mam zainstalowanego na moim komputerze z systemem Windows truskawkowy perl. Kiedy uruchamiam perl -e 'print time, "\n" 'w PowerShell, widzę dane wyjściowe takie jak 1321375663SCALAR(0x15731d4). Muszę uciec od podwójnych cudzysłowów, aby działał zgodnie z oczekiwaniami:perl -e 'print time, \"\n\" '

Rozgwiazda
źródło
1

Po pierwsze, wiersz poleceń nie jest interpretatorem poleceń. ( Wiersz polecenia jest wyświetlany przez interpreter poleceń. ) Po drugie, interpreter poleceń, wyświetlane monity i konsole Win32 nie mają z tym nic wspólnego.

W programach Win32 podzielenie wiersza poleceń na „słowa” - wielobajtowe łańcuchy znaków zakończone NUL, które programy w językach C i C ++ widzą jako przekazaną tablicę argumentów main()- należą do bibliotek wykonawczych tych programów. W systemach Unices i Linux powłoka dzieli słowa, ponieważ system operacyjny faktycznie działa w oparciu o tablicę ciągów argumentów. Nie dotyczy to Win32. W systemie Win32 sam system operacyjny działa w kategoriach ogona polecenia : pojedynczego długiego łańcucha, który wciąż zawiera wszystkie znaki cudzysłowu, które pierwotnie wpisano w wierszu polecenia. (Nie jest niektóre przetwarzanie wykonane na tym ogonie polecenia przez interpretera poleceń przed przekazaniem go do programu docelowego, ale nie jest to związane z dzieleniem słów.)

W twoim przypadku biblioteka środowiska wykonawczego dla twojego hgprogramu jest dostarczana z następującą komendą:

commit -m „Wstępne zatwierdzenie”

Biblioteka środowiska wykonawczego, z którą został skompilowany ten program, nie wie, że miałeś na myśli pojedynczy znak cudzysłowu, który ma być znakiem cudzysłowu, ponieważ nie jest to konwencja . Konwencja dotyczy tylko podwójnych cudzysłowów (i odwrotnych ukośników przed podwójnymi cudzysłowami).

Konwencja ta jest wbudowana w bibliotekę wykonawczą dostarczoną wraz z kompilatorem używanym do tworzenia programu. Jeśli chcesz zmienić konwencję, będziesz musiał ponownie połączyć każdy program, który chcesz uruchomić w ten sposób, ze specjalną własną biblioteką wykonawczą, która rozpoznaje również pojedyncze cudzysłowy. Oczywiście jest to niepraktyczne (chyba że są to wszystkie programy Cygwin).

O wiele bardziej praktyczne podejście polega na robieniu tego, co już robisz: rozpoznaj, że Windows nie jest Uniksem i odpowiednio dostosuj przykłady przed ich użyciem.

JdeBP
źródło
1
Trudno mi zrozumieć znaczenie twojej odpowiedzi. W każdym razie zaktualizowałem swoje pytanie.
zaznacz
Nie wszystko zależy od czasu wykonywania, ponieważ mimo że program pobiera to wszystko za jednym razem, sam interpreter cmd interpretuje pojedyncze cudzysłowy inaczej niż podwójne. np. jeśli wpiszesz „&”, to & jest dosłowne, a „&” jest przekazany jako parametr, różni się od „&”, ponieważ ampersand- i będą traktowane jako specjalne i nie zostaną przekazane. Również cmd /? ma kilka reguł, które, jak przypuszczam, dotyczą interpretera cmd, a nie środowiska wykonawczego.
barlop
0

Jestem pewien, że nie możesz edytować sposobu, w jaki DOS analizuje polecenia. Jest to nieodłączne od programowania podstawowego.

Jedynym rozwiązaniem, które mogę wymyślić, aby przyspieszyć, jest pozostawienie otwartego okna Notatnika i uruchomienie „Znajdź i zamień” - zastępując wszystkie pojedyncze cudzysłowy podwójnymi cudzysłowami. Następnie stamtąd kopiuj i wklej do DOS.

akseli
źródło
1
Nie wiem o 9X's command.com (przypuszczam, że to jest DOS! A 9X jest prawdopodobnie nadal dodatkiem do DOS), ale CMD.EXE NT nie jest DOS! DOS to system operacyjny. CMD.EXE to dodatek w systemie operacyjnym NT i nie będzie działał poza nim. Podałem -1 za nazwanie go DOS, bardzo amatorsko jest nazywać NTD.exe / „procesorem poleceń systemu Windows” „DOS”.
barlop