Mengapa saya mendapatkan "baris 1: $ ': \ r': perintah tidak ditemukan"?

13

Saya menggunakan Cygwin di laptop saya (DOS). Saya memiliki koleksi skrip dari kolega saya, dan saya sendiri. Saya bukan orang IT, tidak berpengetahuan luas di Unix. Saya mengikuti sintaks kolega saya dan mampu mengelola beberapa hal sederhana.

Skrip bekerja dengan baik di laptop lama saya. Saya baru saja mengganti laptop, menginstal Cygwin. Ketika saya menjalankan skrip saya, mereka tidak berfungsi. Berikut adalah salah satu contoh pesan kesalahan yang saya dapatkan:

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

Inilah 5 baris teratas dari skrip saya

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

Bisakah seseorang tolong jelaskan bagaimana saya bisa mengatasi masalah ini?

TPham
sumber

Jawaban:

28

Anda memiliki ujung garis bergaya Windows.

Perintah no-op :malah dibaca sebagai :<carriage return>, ditampilkan sebagai :\ratau lebih lengkap $':\r'.

Jalankan dos2unix scriptnamedan Anda harus baik-baik saja.


Jika belum dos2unix, berikut ini akan berfungsi hampir di mana saja (dan saya uji pada MobaXterm di Windows):

vi -b filename

Kemudian di vi, ketik:

:%s/\r$//
:x

Anda baik untuk pergi.


Di vim, untuk apa Anda menggunakan Cygwin vi, ada beberapa cara untuk melakukan ini. Yang lain melibatkan fileformatpengaturan, yang dapat mengambil nilai dosatau unix. Baik secara eksplisit mengubahnya setelah memuat file dengan

set fileformat = unix
atau secara eksplisit memaksa format file saat menulis file dengan

: w + fileformat = unix

Untuk lebih lanjut tentang ini, lihat banyak pertanyaan dan jawaban di sini yang membahas masalah ini, termasuk:

Wildcard
sumber
Hanya ingin mengklarifikasi, "iter = 1" adalah penghitung saya yang akan digunakan untuk jumlah putaran algoritma matematika yang model saya harus ulangi nanti di luar garis 5. Saya hanya memposting 5 baris teratas untuk pergi dengan pesan eror. Semua komentar dan instruksi sangat dihargai !!
TPham
Saya baru saja mencoba perintah yang disarankan "$ tr -d ....." tetapi ada yang salah dengan laptop saya. Itu tidak kembali ke "$" tetapi ">" muncul di layar sebagai gantinya. Saya harus menggunakan contrl C untuk keluar. Kemudian, saya menguji skrip untuk melihat apakah masalahnya sudah diperbaiki, tetapi masih ada. Maaf, pengetahuan saya di bidang ini sangat minim! Saya mencoba memanfaatkan koleksi skrip saya karena sangat membantu pekerjaan saya. Terima kasih semuanya telah bersabar dan membantu saya.
TPham
@TPham, lihat edit. Jika ini berhasil, pastikan untuk menggunakan tanda centang di sebelah jawaban untuk "menerimanya". (Terima jawaban mana yang paling baik menyelesaikan masalah Anda.) Unix.stackexchange.com/help/someone-answers
Wildcard
1
Perintah-perintah yang merupakan kata-kata tidak terlalu rumit bagi seorang pemula daripada mantra misterius yang hampir seluruhnya merupakan tanda baca. Ini tidak membutuhkan jawaban terpisah. Hanya perlu jawaban ini untuk menyebutkan yang vimdapat melakukan ini dalam dua cara, salah satunya menggunakan kata-kata. Atau, lebih baik lagi, untuk menunjuk ke mana tugas bawahan ini sudah dijawab di atas dan di sini di jauh lebih rinci daripada setiap jawaban pada halaman ini, termasuk unix.stackexchange.com/questions/88811 hanya untuk pemula.
JdeBP
1
Perhatikan bahwa vi -b, \rekstensi vim pula. tidak POSIX, tidak dalam nvi, elvis, Solaris vi ...
Stéphane Chazelas
10

Ini karena skrip telah disimpan oleh editor yang menggunakan akhir baris DOS (seperti Notepad ++, misalnya). Anda harus menghapus ini dari skrip Anda.

Untuk melakukan ini, gunakan dos2unixpada file skrip, atau

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

(ini akan menghapus semua pengembalian carriage dari mana saja dalam skrip)


Adapun kode dalam skrip:

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

Ini mungkin terlihat seperti

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

Ini menghapus file 1.txtdari direktori saat ini, jika ada. The :perintah tidak apa-apa (hampir) dan dapat dihapus. Nilai itervariabel harus digunakan sebagai $iter, dan dikutip. Dan kemudian saya mungkin lebih eksplisit daripada kebutuhan dengan menggunakan ./untuk mengatakan bahwa file perlu ditemukan di direktori saat ini.

Jika Anda berencana untuk mengubah ini menjadi sebuah loop (di sini, menghapus semua 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

Atau, jika kita merasa licik / malas,

rm -f {1..10}.txt

di shell yang mengerti ekspansi brace.

Kusalananda
sumber
3
Notepad ++ sebenarnya memiliki opsi untuk menggunakan jeda baris Windows / Mac / Linux. Anda hanya perlu pergi ke menu Edit dan kemudian EOL Conversion-> Unix (LF). Atau Anda bisa mengklik dua kali di sudut kanan bawah di mana dikatakan Windows (CR LF)dan mengubahnya keUnix (LF)
jesse_b
Terima kasih semuanya atas instruksi Anda. Ingin mengklarifikasi: "iter = 1" adalah penghitung yang saya gunakan nanti untuk tujuan utama saya, di luar garis 5.
TPham
@TPham Sama-sama. Saya hanya bosan dan mengambil kode Anda dan membiarkan pikiran saya berjalan impresionistis dengannya.
Kusalananda
Atau rm -f [1-9].txt 10.txt. Tapi itu tidak benar-benar logis setara, seakan tidak ada file 1-9 tetapi ada adalah file harfiah disebut [1-9].txtmaka akan dihapus. : D
Wildcard
5

Skrip Anda memiliki akhiran baris yang salah. Windows menggunakan CR + LF (\ r \ n), Unix menggunakan LF (\ n), dan Classic MacOS menggunakan CR (\ r). Anda harus mengubah akhir baris pada semua file yang terpengaruh, baik dengan editor teks atau alat mandiri seperti dos2unix.

Sistem kontrol versi dan FTP seperti SVN cenderung dapat mengkonversi akhir baris dengan tepat, jadi Anda mungkin ingin melihat opsi-opsi untuk mentransfer file di masa depan.

Jika file-file ini tidak ditransfer, tetapi hanya digunakan pada satu mesin, maka Anda akan ingin menemukan pengaturan untuk akhir baris di editor teks pilihan Anda. Sebagian besar yang diiklankan sebagai "untuk pemrogram" akan memiliki opsi seperti itu.

Rubah
sumber
Terima kasih semuanya atas instruksi Anda yang bermanfaat. Saya baru saja mencoba dos2unix tetapi sepertinya saya tidak memilikinya. Akan mencari dan mencobanya lagi.
TPham
3

Sebagai jawaban tambahan izinkan saya menambahkan beberapa catatan / tips ...

Pertama, untuk file teks biasa Anda dapat dengan mudah menentukan apakah mereka memiliki baris Unix atau DOS yang berakhir menggunakan fileperintah. Sebagai contoh:

$ 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

Perhatikan penggunaan saya atas dos2unix. Saya sangat menyarankan Anda menginstalnya. Bergantung pada bagaimana Anda menggunakan Cygwin, Anda mungkin perlu melakukan konversi ini cukup sering sehingga kenyamanan diterima. Lebih penting lagi, tidak ada kemungkinan kesalahan seperti yang Anda dapatkan dengan pengeditan manual yang dibahas di sini.

Untuk menginstal, jalankan Cygwin utama yang dapat dieksekusi. Itu yang dengan nama seperti setup-x86_64.exe atau sesuatu seperti itu. Pastikan Anda melihat layar seperti ini:

masukkan deskripsi gambar di sini

Karena Anda sudah melakukan instalasi utama, Anda harus dapat mengeklik Berikutnya sampai Anda mendapatkan layar pilihan. Pilih Penuh di dropdown dan masukkan "dos2" di kotak pencarian dan pilih alat seperti yang ditunjukkan di sini:

masukkan deskripsi gambar di sini

Kemudian klik Next lagi dan biarkan instalasi selesai. Itu dia. Selamat bersenang-senang. Cygwin, dengan pengecualian ketidaknyamanan sesekali ini, adalah paket yang luar biasa.

B Layer
sumber
Terima kasih banyak atas instruksi Anda B Layer! Grup Stack Exchange ini sangat membantu. Saya sangat menghargai dukungan ini.
TPham
1

Jika tidak dos2unix, ada juga 'flip'

$ flip -u yourfilename.txt

akan membaliknya menggunakan ujung garis unix.

chai
sumber
1

Saya menggunakan Notepad ++ untuk mengedit skrip bash (.sh) saya dengan menghubungkan ke server dengan WinSCP
(Untuk mengatur editor WinSCP ke Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Ini sangat praktis untuk membuka file dari server untuk diedit / disimpan daripada editor " Vim ".
Ketika Anda membuka file di Notepad ++ , klik dua kali pada kolom 7 di bilah status di bagian bawah dan pilih " Unix (LF) ".

masukkan deskripsi gambar di sini

Anda juga harus mengubah yang ke-8 dengan Encoding -> Encode di UTF-8 di bar bagian atas.

Alper t. Turker
sumber
0

Anda tidak perlu mengubah pengkodean baris file yang sebenarnya agar Bash Cygwin bekerja dengan senang hati dengan pengkodean end-of-line Mac dan Windows. Ada opsi yang Anda butuhkan untuk menyalakannya.

Cukup perbarui ~/.bash_profilesehingga berisi

export SHELLOPTS
set -o igncr

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

swdev
sumber