Perché ricevo “riga 1: $ ': \ r': comando non trovato”?


13

Ho usato Cygwin sul mio laptop (DOS). Ho una raccolta di script dei miei colleghi e dei miei. Non sono una persona IT, non sono esperto in Unix. Seguo la sintassi dei miei colleghi e sono in grado di gestire alcune cose semplici.

Gli script hanno funzionato bene sul mio vecchio laptop. Ho appena cambiato laptop, installato Cygwin. Quando eseguo i miei script, non funzionano. Ecco un esempio del messaggio di errore che ottengo:

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

Ecco le prime 5 righe della mia sceneggiatura

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

Qualcuno può spiegare come posso aggirare questo problema?

Risposte:


28

Hai terminazioni di linea in stile Windows.

Il comando no-op :viene invece letto come :<carriage return>, visualizzato come :\ro più completamente come $':\r'.

Corri dos2unix scriptnamee dovresti stare bene.


In caso contrario dos2unix, dovrebbe funzionare quasi ovunque (e ho testato su MobaXterm su Windows):

vi -b filename

Quindi vi, digitare:

:%s/\r$//
:x

Sei a posto.


In vim, che è quello che stai usando su Cygwin vi, ci sono molti modi per farlo. Un altro riguarda l' fileformatimpostazione, che può assumere i valori doso unix. O cambiarlo esplicitamente dopo aver caricato il file con

set fileformat = unix
o forzare esplicitamente il formato del file quando si scrive il file con

: w + fileformat = unix

Per ulteriori informazioni al riguardo, consulta le numerose domande e risposte qui relative a questo argomento, tra cui:


Voglio solo chiarire, "iter = 1" è il mio contatore che verrà utilizzato per il numero di round di un algoritmo matematico che il mio modello dovrà ripetere in seguito oltre la riga 5. Ho appena pubblicato le prime 5 righe per andare con messaggio di errore. Tutti i commenti e le istruzioni sono molto apprezzati !!
TPham,

Ho appena provato il comando suggerito "$ tr -d ....." ma c'è qualcosa che non va nel mio laptop. Non torna a "$" ma sullo schermo appare ">". Devo usare il control C per uscire. Quindi, ho testato lo script per vedere se il problema è stato risolto, ma è ancora lì. Mi dispiace, la mia conoscenza in questo campo è minima! Sto cercando di utilizzare la mia raccolta di script in quanto aiutano il mio lavoro così tanto. Grazie a tutti per essere paziente e disponibile con me.
TPham,

@TPham, vedi modifica. Se funziona, assicurati di usare il segno di spunta accanto alla risposta per "accettarlo". (Accetta qualsiasi risposta risolva meglio il tuo problema.) Unix.stackexchange.com/help/someone-answers
Wildcard

1
I comandi che sono parole non sono davvero più complicati per un principiante di un misterioso incantesimo che è quasi interamente punteggiatura. Questo non ha bisogno di una risposta separata. Ha solo bisogno di questa risposta per menzionare che vimpuò farlo in due modi, uno dei quali usa le parole. O, ancora meglio, indicare dove questo compito subordinato è stato risposto più e più volte qui in modo molto più dettagliato di qualsiasi risposta in questa pagina, incluso unix.stackexchange.com/questions/88811 solo per cominciare.
JdeBP,

1
Si noti che vi -b, \rsono estensioni di vim comunque. non POSIX, non in nvi, elvis, Solaris vi ...
Stéphane Chazelas,

10

Ciò è dovuto al fatto che lo script è stato salvato da un editor che utilizza i finali di riga DOS (come ad esempio Notepad ++). Dovrai rimuoverli dai tuoi script.

Per fare ciò, utilizzare dos2unixsul file di script o

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

(questo rimuoverà tutti i ritorni a capo da qualsiasi punto dello script)


Per quanto riguarda il codice nello script:

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

Questo dovrebbe probabilmente assomigliare a qualcosa

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

Ciò rimuove il file 1.txtdalla directory corrente, se esiste. Il :comando non fa nulla (quasi) e può essere rimosso. Il itervalore della variabile deve essere usato come $itered essere quotato. E poi forse sto diventando più esplicito di quanto sia necessario usando ./per dire che il file deve essere trovato nella directory corrente.

Se avete in programma di trasformare questo in un ciclo (qui, l'eliminazione di tutti i file 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

Oppure, se ci sentiamo subdoli / pigri,

rm -f {1..10}.txt

in gusci che comprende l'espansione del controvento.


3
Notepad ++ ha effettivamente l'opzione per usare le interruzioni di linea di Windows / Mac / Linux. Devi solo andare al menu Modifica e quindi Conversione EOL-> Unix (LF). Oppure puoi semplicemente fare doppio clic nell'angolo in basso a destra dove dice Windows (CR LF)e cambiarlo inUnix (LF)
jesse_b

Grazie a tutti per le vostre istruzioni. Vorrei chiarire: "iter = 1" è un contatore che userò in seguito per il mio obiettivo principale, oltre la linea 5.
TPham

@TPham Prego. Ero solo annoiato, ho preso il tuo codice e ho lasciato che la mia mente fosse impressionista.
Kusalananda

Or rm -f [1-9].txt 10.txt. Ma non è del tutto logicamente equivalenti, come se non ci sono file 1-9 ma non v'è un file chiamato letteralmente [1-9].txtallora sarà cancellato. : D
Wildcard

5

I tuoi script hanno le terminazioni di riga errate. Windows utilizza CR + LF (\ r \ n), Unix utilizza LF (\ n) e Classic MacOS utilizza CR (\ r). Dovrai modificare le terminazioni di riga su tutti i file interessati, con un editor di testo o uno strumento autonomo come dos2unix.

I sistemi FTP e di controllo della versione come SVN tendono a essere in grado di convertire le terminazioni di linea in modo appropriato, quindi potresti voler esaminare quelle opzioni per il trasferimento di file in futuro.

Se questi file non vengono trasferiti, ma utilizzati solo su un singolo computer, ti consigliamo di trovare le impostazioni per le terminazioni di riga nel tuo editor di testo preferito. La maggior parte di quelli che sono pubblicizzati come "per programmatori" avranno tale opzione.


Grazie a tutti per le vostre utili istruzioni. Ho appena provato Dos2unix ma sembra che non ce l'ho. Cercherà e riproverà.
TPham,

3

Come risposta supplementare, vorrei aggiungere un paio di note / suggerimenti ...

Innanzitutto, per i normali file di testo è possibile determinare facilmente se hanno terminazioni di riga Unix o DOS mediante il filecomando. Per esempio:

$ 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

Nota il mio uso di dos2unix. Consiglio vivamente di installarlo. A seconda di come usi Cygwin, potresti scoprire che devi fare questa conversione abbastanza spesso da dare il benvenuto alla comodità. Ancora più importante, non vi è alcuna possibilità di errore come si ottiene con le modifiche manuali discusse qui.

Per installare avviare il file eseguibile Cygwin principale. Questo è quello con il nome come setup-x86_64.exe o qualcosa del genere. Assicurati di vedere una schermata come questa:

inserisci qui la descrizione dell'immagine

Poiché hai già eseguito l'installazione primaria, dovresti essere in grado di fare clic su Avanti fino a quando non viene visualizzata la schermata di selezione. Seleziona Completo nel menu a discesa e inserisci "dos2" nella casella di ricerca e scegli lo strumento come mostrato qui:

inserisci qui la descrizione dell'immagine

Quindi fare di nuovo clic su Avanti e completare l'installazione. Questo è tutto. Divertiti. Cygwin, ad eccezione di questo inconveniente occasionale, è un pacchetto fantastico.


Grazie mille per le tue istruzioni B Layer! Questo gruppo di scambio di stack è molto utile. Apprezzo molto questo supporto.
TPham,

1

Se non dos2unix, c'è anche 'flip'

$ flip -u yourfilename.txt

lo passerà all'utilizzo delle terminazioni di linea unix.


1

Uso Notepad ++ per modificare i miei script bash (.sh) collegandomi al server tramite WinSCP
(per impostare l'editor WinSCP su Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Questo è molto pratico per aprire file dai server da modificare / salvare invece dell'editor " Vim ".
Quando apri il file in Notepad ++ , fai doppio clic sulla settima colonna nella barra di stato in basso e seleziona " Unix (LF) ".

inserisci qui la descrizione dell'immagine

Inoltre, devi cambiare l'ottavo con Codifica -> Codifica in UTF-8 nella barra in alto.


0

Non è necessario modificare la codifica di riga del file effettivo per consentire a Cygwin's Bash di funzionare perfettamente con le codifiche di fine linea di Mac e Windows. C'è un'opzione che devi solo attivare.

Basta aggiornare il tuo in ~/.bash_profilemodo che contenga

export SHELLOPTS
set -o igncr

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.