Dlaczego otrzymuję „wiersz 1: $ ': \ r': polecenie nie znaleziono”?

13

Użyłem Cygwina na moim laptopie (DOS). Mam kolekcję skryptów od moich kolegów i własną. Nie jestem informatykiem, nie znam się na Uniksie. Śledzę składnię moich kolegów i potrafię zarządzać kilkoma prostymi rzeczami.

Skrypty działały dobrze na moim starym laptopie. Właśnie zmieniłem laptopa, zainstalowałem Cygwin. Kiedy uruchamiam skrypty, one nie działają. Oto jeden przykład komunikatu o błędzie, który otrzymuję:

line 1: $':\r': command not found
line 5: syntax error near unexpected token `$'\r''
line 5: `fi

Oto 5 pierwszych linii mojego skryptu

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Czy ktoś może wyjaśnić, jak mogę obejść ten problem?

TPham
źródło

Odpowiedzi:

29

Masz zakończenia linii w stylu Windows.

:Zamiast tego polecenie no-op jest odczytywane jako :<carriage return>, wyświetlane jako :\rlub pełniej jako $':\r'.

Uciekaj dos2unix scriptnamei powinno być dobrze.


Jeśli nie masz dos2unix, poniższe powinny działać prawie wszędzie (a ja testowałem na MobaXterm w systemie Windows):

vi -b filename

Następnie viwpisz:

:%s/\r$//
:x

Możesz iść.


W vim, do czego używasz Cygwin vi, istnieje wiele sposobów na zrobienie tego. Kolejny dotyczy fileformatustawienia, które może przyjmować wartości doslub unix. Albo jawnie zmień go po załadowaniu pliku

ustaw format pliku = unix
lub jawnie wymuś format pliku podczas zapisywania pliku za pomocą

: w + format pliku = uniksowy

Aby uzyskać więcej informacji na ten temat, zobacz wiele pytań i odpowiedzi na ten temat, w tym:

Dzika karta
źródło
Chcę tylko wyjaśnić, „iter = 1” to mój licznik, który będzie używany do liczby rund algorytmu matematycznego, który mój model będzie musiał powtórzyć później poza linią 5. Właśnie opublikowałem 5 najlepszych linii, aby przejść z Komunikat o błędzie. Wszystkie uwagi i instrukcje są mile widziane !!
TPham
Właśnie wypróbowałem sugerowane polecenie „$ tr -d .....”, ale coś jest nie tak z moim laptopem. Nie wraca do „$”, ale zamiast tego na ekranie pojawia się „>”. Muszę użyć contrl C, żeby się wydostać. Następnie przetestowałem skrypt, aby sprawdzić, czy problem został rozwiązany, ale nadal występuje. Przepraszamy, moja wiedza w tej dziedzinie jest bardzo minimalna! Próbuję wykorzystać moją kolekcję skryptów, ponieważ bardzo pomagają mi w pracy. Dziękuję wszystkim za cierpliwość i pomoc.
TPham
@TPham, patrz edycja. Jeśli to zadziała, użyj zaznaczenia obok odpowiedzi, aby ją „zaakceptować”. (Zaakceptuj dowolną odpowiedź, która najlepiej rozwiąże Twój problem). Unix.stackexchange.com/help/someone-answers
Wildcard
1
Polecenia będące słowami nie są tak naprawdę bardziej skomplikowane dla nowicjuszy niż tajemnicze zaklęcie, które jest prawie całkowicie interpunkcyjne. To nie wymaga osobnej odpowiedzi. Potrzebuje jedynie tej odpowiedzi, aby wspomnieć, że vimmożna to zrobić na dwa sposoby, z których jeden używa słów. Lub jeszcze lepiej, aby wskazać, gdzie na to podrzędne zadanie zostało w kółko udzielone, o wiele bardziej szczegółowe niż jakakolwiek odpowiedź na tej stronie, w tym unix.stackexchange.com/questions/88811 tylko na początek.
JdeBP,
1
Zauważ, że vi -bi tak \rsą rozszerzeniami vima. nie POSIX, nie w nvi, elvis, Solaris vi ...
Stéphane Chazelas 19.09.17
10

Wynika to z zapisania skryptu przez edytor korzystający z końcówek linii DOS (na przykład Notepad ++). Będziesz musiał usunąć je ze swoich skryptów.

Aby to zrobić, użyj albo dos2unixw pliku skryptu, albo

$ tr -d '\r' <script >script.new && mv script.new script

(spowoduje to usunięcie wszystkich zwrotów karetki z dowolnego miejsca w skrypcie)


Jeśli chodzi o kod w skrypcie:

:
iter=1
if [ -f iter.txt ]
   then rm ./iter.txt 
fi  

Powinno to wyglądać mniej więcej tak

iter=1
if [ -f "./$iter.txt" ]; then
   rm "./$iter.txt"
fi

Spowoduje to usunięcie pliku 1.txtz bieżącego katalogu, jeśli istnieje. :Polecenie nie robi nic (prawie) i mogą być usunięte. Wartość iterzmiennej powinna być używana jako $iteri cytowana. A potem jestem prawdopodobnie bardziej wyraźny, niż trzeba, ./mówiąc, że plik należy znaleźć w bieżącym katalogu.

Jeśli masz zamiar przekształcić pętli (tutaj, usuwając wszystkie pliki 1.txt, 2.txt..., 10.txt):

iter=1
while [ "$iter" -le 10 ]; then
    if [ -f "./$iter.txt" ]; then
        rm "./$iter.txt"
    fi
    iter=$(( iter + 1 ))
done

Lub jeśli czujemy się podstępni / leniwi,

rm -f {1..10}.txt

w powłokach, które rozumieją rozwinięcie nawiasu klamrowego.

Kusalananda
źródło
3
Notepad ++ faktycznie ma opcję użycia podziałów linii Windows / Mac / Linux. Wystarczy przejść do menu Edycja, a następnie Konwersja EOL-> Unix (LF). Lub możesz po prostu dwukrotnie kliknąć w prawym dolnym rogu, gdzie jest napisane, Windows (CR LF)i zmienić naUnix (LF)
jesse_b
Dziękuję wszystkim za instrukcje. Chciałbym wyjaśnić: „iter = 1” to licznik, którego używam później do mojego głównego celu, poza linią 5.
TPham
@TPham Nie ma za co. Byłem po prostu znudzony i wziąłem twój kod i pozwoliłem, aby mój umysł działał impresjonistycznie.
Kusalananda
Lub rm -f [1-9].txt 10.txt. Ale to nie jest całkowicie logicznie równoważne, jakby nie istnieją żadne pliki, 1-9, ale nie jest to plik o nazwie dosłownie [1-9].txtnastępnie zostanie ona usunięta. : D
Wildcard,
5

Twoje skrypty mają niewłaściwe zakończenia linii. Windows używa CR + LF (\ r \ n), Unix używa LF (\ n), a Classic MacOS używa CR (\ r). Musisz zmienić zakończenia wszystkich plików, których dotyczy problem, za pomocą edytora tekstu lub samodzielnego narzędzia, takiego jak dos2unix.

Systemy FTP i kontroli wersji, takie jak SVN, zwykle potrafią odpowiednio konwertować zakończenia linii, więc możesz zajrzeć do tych opcji przesyłania plików w przyszłości.

Jeśli te pliki nie są przesyłane, ale są po prostu używane na jednym komputerze, będziesz chciał znaleźć ustawienia zakończeń linii w preferowanym edytorze tekstu. Większość reklamowanych jako „dla programistów” będzie miała taką opcję.

Lis
źródło
Dziękuję wszystkim za pomocne instrukcje. Właśnie próbowałem dos2unix, ale wygląda na to, że go nie mam. Wyszuka i spróbuje ponownie.
TPham
3

Jako dodatkową odpowiedź pozwól mi dodać kilka notatek / wskazówek ...

Po pierwsze, w przypadku zwykłych plików tekstowych można łatwo ustalić, czy mają one końcówkę linii uniksowej czy DOS za pomocą filepolecenia. Na przykład:

$ file test.txt
test.txt: ASCII text, with CRLF line terminators
$ dos2unix test.txt
dos2unix: converting file test.txt to Unix format...
$ file test.txt
test.txt: ASCII text

Zwróć uwagę na moje użycie dos2unix. Bardzo polecam go zainstalować. W zależności od tego, jak korzystasz z Cygwin, może być konieczne wykonywanie tej konwersji wystarczająco często, aby wygoda była mile widziana. Co ważniejsze, nie ma szans na błąd, jak w przypadku omawianych tutaj ręcznych zmian.

Aby zainstalować, uruchom główny plik wykonywalny Cygwin. To ten o nazwie setup-x86_64.exe lub coś w tym stylu. Upewnij się, że widzisz taki ekran:

wprowadź opis zdjęcia tutaj

Ponieważ już wykonałeś podstawową instalację, powinieneś być w stanie kliknąć Dalej do końca, aż pojawi się ekran wyboru. Wybierz Pełny z menu rozwijanego i wpisz „dos2” w polu wyszukiwania i wybierz narzędzie, jak pokazano tutaj:

wprowadź opis zdjęcia tutaj

Następnie ponownie kliknij przycisk Dalej i pozwól instalacji zakończyć. Otóż ​​to. Baw się dobrze. Cygwin, z wyjątkiem tych sporadycznych niedogodności, jest niesamowitym pakietem.

Warstwa B.
źródło
Bardzo dziękuję za instrukcję Warstwa B! Ta grupa wymiany stosów jest bardzo pomocna. Naprawdę doceniam to wsparcie.
TPham
1

Jeśli nie dos2unix, istnieje również „flip”

$ flip -u twoja nazwa pliku.txt

zamieni go na użycie zakończeń linii unix.

Chai
źródło
1

Używam Notepad ++ do edycji moich skryptów bash (.sh), łącząc się z serwerem za pomocą WinSCP
(aby skonfigurować edytor WinSCP do Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Jest to bardzo praktyczne przy otwieraniu plików z serwerów do edycji / zapisywania zamiast edytora „ Vim ”.
Po otwarciu pliku w Notepad ++ kliknij dwukrotnie siódmą kolumnę na pasku stanu na dole i wybierz „ Unix (LF) ”.

wprowadź opis zdjęcia tutaj

Musisz także zmienić ósmy, kodując -> Zakoduj w UTF-8 na górnym pasku.

Alper t. Turker
źródło
0

Nie trzeba zmieniać faktycznego kodowania linii pliku, aby Cygwin's Bash z przyjemnością współpracował z kodowaniem końca linii w systemie Mac i Windows. Istnieje opcja, którą musisz tylko włączyć.

Po prostu zaktualizuj, ~/.bash_profileaby zawierał

export SHELLOPTS
set -o igncr

Zobacz https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html

swdev
źródło