Warum erhalte ich den Befehl "Zeile 1: $ ': \ r': Befehl nicht gefunden"?

12

Ich habe Cygwin auf meinem Laptop (DOS) verwendet. Ich habe eine Sammlung von Skripten meiner Kollegen und meiner eigenen. Ich bin keine IT-Person und kenne mich mit Unix nicht aus. Ich folge der Syntax meiner Kollegen und kann ein paar einfache Dinge verwalten.

Die Skripte funktionierten gut auf meinem alten Laptop. Ich habe gerade den Laptop gewechselt und Cygwin installiert. Wenn ich meine Skripte ausführe, funktionieren sie nicht. Hier ist ein Beispiel für die Fehlermeldung, die ich erhalte:

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

Hier sind die obersten 5 Zeilen meines Skripts

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

Kann mir bitte jemand erklären, wie ich dieses Problem umgehen kann?

TPham
quelle

Antworten:

27

Sie haben Zeilenenden im Windows-Stil.

Der Befehl no-op :wird stattdessen als gelesen :<carriage return>, als :\roder vollständiger als angezeigt $':\r'.

Lauf dos2unix scriptnameund es sollte dir gut gehen.


Wenn Sie nicht haben dos2unix, sollte das Folgende fast überall funktionieren (und ich habe auf MobaXterm unter Windows getestet):

vi -b filename

Geben Sie dann viFolgendes ein:

:%s/\r$//
:x

Du bist gut zu gehen.


In vim, wofür Sie Cygwin verwenden vi, gibt es mehrere Möglichkeiten, dies zu tun. Eine andere beinhaltet die fileformatEinstellung, die die Werte dosoder annehmen kann unix. Ändern Sie es entweder explizit nach dem Laden der Datei mit

setze fileformat = unix
oder erzwingen Sie explizit das Dateiformat, wenn Sie die Datei mit ausschreiben

: w + Dateiformat = Unix

Weitere Informationen hierzu finden Sie in den zahlreichen Fragen und Antworten zu diesem Thema, darunter:

Platzhalter
quelle
Ich möchte nur klarstellen, dass "iter = 1" mein Zähler ist, der für die Anzahl der Runden eines mathematischen Algorithmus verwendet wird, den mein Modell später über Zeile 5 hinaus wiederholen muss. Ich habe gerade die obersten 5 Zeilen für die Zeile gepostet Fehlermeldung. Alle Kommentare und Anweisungen werden sehr geschätzt !!
TPham
Ich habe gerade den vorgeschlagenen Befehl "$ tr -d ....." ausprobiert, aber mit meinem Laptop stimmt etwas nicht. Es geht nicht zurück zu "$", sondern das ">" erscheint stattdessen auf dem Bildschirm. Ich muss Steuerung C verwenden, um rauszukommen. Dann habe ich das Skript getestet, um festzustellen, ob das Problem behoben ist, aber es ist immer noch vorhanden. Entschuldigung, meine Kenntnisse auf diesem Gebiet sind sehr gering! Ich versuche, meine Sammlung von Skripten zu nutzen, da sie meiner Arbeit so sehr helfen. Vielen Dank an alle, die geduldig und hilfsbereit für mich waren.
TPham
@TPham, siehe bearbeiten. Wenn dies funktioniert, verwenden Sie das Häkchen neben der Antwort, um sie zu "akzeptieren". (Akzeptieren Sie die Antwort, die Ihr Problem am besten gelöst hat.) Unix.stackexchange.com/help/someone-answers
Wildcard
1
Befehle, die Wörter sind, sind für einen Anfänger nicht wirklich komplizierter als eine mysteriöse Beschwörung, die fast ausschließlich Interpunktion ist. Dies erfordert keine separate Antwort. Diese Antwort muss lediglich erwähnt werden, dass vimdies auf zwei Arten möglich ist, von denen eine Wörter verwendet. Oder, noch besser, um darauf hinzuweisen, wo diese untergeordnete Aufgabe hier immer wieder ausführlicher beantwortet wurde als jede Antwort auf dieser Seite, einschließlich unix.stackexchange.com/questions/88811, nur für den Anfang.
JdeBP
1
Beachten Sie, dass vi -b, \rsind vim Erweiterungen sowieso. nicht POSIX, nicht in nvi, elvis, Solaris vi ...
Stéphane Chazelas
10

Dies liegt daran, dass das Skript von einem Editor gespeichert wurde, der DOS-Zeilenenden verwendet (z. B. Notepad ++). Sie müssen diese aus Ihren Skripten entfernen.

Verwenden Sie dazu entweder dos2unixdie Skriptdatei oder

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

(Dadurch werden alle Wagenrückläufe von einer beliebigen Stelle im Skript entfernt.)


Wie für den Code im Skript:

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

Dies sollte möglicherweise so aussehen

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

Dadurch wird die Datei 1.txtaus dem aktuellen Verzeichnis entfernt, sofern vorhanden. Der :Befehl macht (fast) nichts und kann entfernt werden. Der iterWert der Variablen sollte als $iterund in Anführungszeichen gesetzt werden. Und dann bin ich möglicherweise expliziter als nötig, indem ./ich sage, dass die Datei im aktuellen Verzeichnis gefunden werden muss.

Wenn Sie planen , dies in einer Schleife zu drehen (hier, um alle Dateien zu löschen 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

Oder wenn wir uns hinterhältig / faul fühlen,

rm -f {1..10}.txt

in Muscheln, die die Ausdehnung der Zahnspange verstehen.

Kusalananda
quelle
3
Notepad ++ bietet tatsächlich die Möglichkeit, Zeilenumbrüche für Windows / Mac / Linux zu verwenden. Sie müssen nur zum Menü Bearbeiten und dann zu EOL Conversion-> Unix (LF) gehen. Oder Sie können einfach in die untere rechte Ecke Windows (CR LF)Unix (LF)
doppelklicken
Vielen Dank an alle für Ihre Anweisung. Ich möchte klarstellen: Der "iter = 1" ist ein Zähler, den ich später für mein Hauptziel jenseits von Zeile 5 verwende.
TPham
@ TPham Gern geschehen. Ich war nur gelangweilt und nahm Ihren Code und ließ meine Gedanken damit impressionistisch werden.
Kusalananda
Oder rm -f [1-9].txt 10.txt. Aber das ist nicht ganz logisch äquivalent, als ob es keine Dateien 1-9 gibt, aber es gibt eine Datei, die buchstäblich aufgerufen wird, [1-9].txtdann wird sie gelöscht. : D
Wildcard
5

Ihre Skripte haben die falschen Zeilenenden. Windows verwendet CR + LF (\ r \ n), Unix verwendet LF (\ n) und Classic MacOS verwendet CR (\ r). Sie müssen die Zeilenenden aller betroffenen Dateien ändern, entweder mit einem Texteditor oder einem eigenständigen Tool wie dos2unix.

FTP- und Versionskontrollsysteme wie SVN sind in der Regel in der Lage, die Zeilenenden entsprechend zu konvertieren. Daher sollten Sie diese Optionen für die zukünftige Übertragung von Dateien prüfen.

Wenn diese Dateien nicht übertragen, sondern nur auf einem einzelnen Computer verwendet werden, sollten Sie die Einstellungen für Zeilenenden in Ihrem bevorzugten Texteditor finden. Die meisten, die als "für Programmierer" beworben werden, haben eine solche Option.

Fuchs
quelle
Vielen Dank an alle für Ihre hilfreiche Anleitung. Ich habe gerade dos2unix ausprobiert, aber es scheint, dass ich es nicht habe. Werde suchen und es erneut versuchen.
TPham
3

Lassen Sie mich als ergänzende Antwort ein paar Anmerkungen / Tipps hinzufügen ...

Erstens können Sie bei normalen Textdateien mit dem fileBefehl leicht feststellen, ob Unix- oder DOS-Zeilen enden . Beispielsweise:

$ 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

Beachten Sie meine Verwendung von dos2unix. Ich empfehle Ihnen dringend, es zu installieren. Je nachdem, wie Sie Cygwin verwenden, müssen Sie diese Konvertierung möglicherweise häufig genug durchführen, damit die Bequemlichkeit erwünscht ist. Noch wichtiger ist, dass bei den hier beschriebenen manuellen Änderungen keine Fehlerwahrscheinlichkeit besteht.

Starten Sie zur Installation die ausführbare Cygwin-Hauptdatei. Das ist der mit dem Namen setup-x86_64.exe oder so ähnlich. Stellen Sie sicher, dass Sie einen Bildschirm wie diesen sehen:

Geben Sie hier die Bildbeschreibung ein

Da Sie die primäre Installation bereits durchgeführt haben, sollten Sie bis zum Auswahlbildschirm auf Weiter klicken können. Wählen Sie Voll in der Dropdown-Liste und geben Sie "dos2" in das Suchfeld ein und wählen Sie das Werkzeug wie hier gezeigt:

Geben Sie hier die Bildbeschreibung ein

Klicken Sie dann erneut auf Weiter und lassen Sie die Installation abschließen. Das ist es. Habe Spaß. Cygwin ist mit Ausnahme dieser gelegentlichen Unannehmlichkeiten ein großartiges Paket.

B Schicht
quelle
Vielen Dank für Ihre Anweisung B Layer! Diese Stack Exchange-Gruppe ist sehr hilfreich. Ich schätze diese Unterstützung sehr.
TPham
1

Wenn nicht dos2unix, gibt es auch 'flip'

$ flip -u yourfilename.txt

dreht es auf Unix-Zeilenenden.

Chai
quelle
1

Ich verwende Notepad ++ , um meine Bash-Skripte (.sh) zu bearbeiten, indem ich über WinSCP eine Verbindung zum Server herstelle.
(So ​​richten Sie den WinSCP-Editor für Notepad ++ ein: https://winscp.net/eng/docs/ui_editor_preferences )

Dies ist sehr praktisch, um Dateien von Servern zum Bearbeiten / Speichern anstelle des " Vim " -Editors zu öffnen .
Wenn Sie die Datei in Notepad ++ öffnen, doppelklicken Sie auf die 7. Spalte in der Statusleiste unten und wählen Sie " Unix (LF) ".

Geben Sie hier die Bildbeschreibung ein

Außerdem müssen Sie die 8. durch Codieren -> In UTF-8 in der oberen Leiste codieren ändern.

Hi-Zir
quelle
0

Sie müssen die tatsächliche Zeilencodierung der Datei nicht ändern, damit Cygwins Bash problemlos mit Mac- und Windows-Zeilenendcodierungen funktioniert. Es gibt eine Option, die Sie nur aktivieren müssen.

Aktualisieren Sie einfach Ihre, ~/.bash_profiledamit es enthält

export SHELLOPTS
set -o igncr

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

swdev
quelle