Tại sao tôi nhận được dòng 1: $ ': \ r': lệnh không được tìm thấy?


13

Tôi đã sử dụng Cygwin trên máy tính xách tay của tôi (DOS). Tôi có một bộ sưu tập các kịch bản từ các đồng nghiệp của tôi và của chính tôi. Tôi không phải là dân IT, không am hiểu về Unix. Tôi theo cú pháp của đồng nghiệp và có thể quản lý một vài điều đơn giản.

Các kịch bản hoạt động tốt trên máy tính xách tay cũ của tôi. Tôi vừa đổi laptop, cài đặt Cygwin. Khi tôi chạy tập lệnh của mình, chúng không hoạt động. Đây là một ví dụ về thông báo lỗi tôi nhận được:

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

Dưới đây là 5 dòng trên cùng của kịch bản của tôi

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

Ai đó có thể vui lòng giải thích làm thế nào tôi có thể khắc phục vấn đề này?

Câu trả lời:


28

Bạn có kết thúc dòng kiểu Windows.

:Thay vào đó, lệnh no-op được đọc là :<carriage return>, hiển thị dưới dạng :\rhoặc đầy đủ hơn $':\r'.

Chạy dos2unix scriptnamevà bạn sẽ ổn thôi.


Nếu bạn không có dos2unix, những thứ sau sẽ hoạt động ở hầu hết mọi nơi (và tôi đã thử nghiệm trên MobaXterm trên Windows):

vi -b filename

Sau đó vi, nhập:

:%s/\r$//
:x

Bạn tốt để đi.


Trong vimđó, đó là những gì bạn đang sử dụng trên Cygwin vi, có nhiều cách để làm điều này. Một số khác liên quan đến fileformatcài đặt, có thể lấy các giá trị doshoặc unix. Thay đổi rõ ràng sau khi tải tệp bằng

đặt fileformat = unix
hoặc ép buộc định dạng tệp khi viết tệp ra

: w + fileformat = unix

Để biết thêm về điều này, hãy xem nhiều câu hỏi và câu trả lời ở đây bao gồm chủ đề này, bao gồm:


Chỉ muốn làm rõ, "iter = 1" là bộ đếm của tôi sẽ được sử dụng cho số vòng của thuật toán toán học mà mô hình của tôi sẽ phải lặp lại sau trên dòng 5. Tôi vừa đăng 5 dòng trên cùng để đi với thông báo lỗi. Tất cả các ý kiến ​​và hướng dẫn được đánh giá rất cao !!
TPham

Tôi vừa thử lệnh được đề xuất "$ tr -d ....." nhưng có gì đó không ổn với máy tính xách tay của tôi. Nó không quay trở lại "$" nhưng thay vào đó ">" xuất hiện trên màn hình. Tôi phải sử dụng contrl C để thoát ra. Sau đó, tôi đã thử nghiệm kịch bản để xem sự cố đã được khắc phục chưa, nhưng nó vẫn còn đó. Xin lỗi, kiến ​​thức của tôi trong lĩnh vực này là rất tối thiểu! Tôi đang cố gắng sử dụng bộ sưu tập các kịch bản của mình vì chúng giúp ích cho công việc của tôi rất nhiều. Cảm ơn mọi người vì đã kiên nhẫn và giúp đỡ tôi.
TPham

@TPham, xem chỉnh sửa. Nếu điều này hoạt động, hãy chắc chắn sử dụng dấu kiểm bên cạnh câu trả lời để "chấp nhận" nó. (Chấp nhận câu trả lời nào giải quyết tốt nhất vấn đề của bạn.) Unix.stackexchange.com/help/someone-answers
Wildcard

1
Các lệnh là những từ không thực sự phức tạp đối với người mới hơn là một câu thần chú bí ẩn gần như hoàn toàn là dấu câu. Điều này không cần một câu trả lời riêng biệt. Nó chỉ cần câu trả lời này để đề cập rằng vimcó thể làm điều này theo hai cách, một trong số đó sử dụng từ ngữ. Hoặc, tốt hơn, để chỉ ra nơi mà nhiệm vụ cấp dưới này đã được trả lời nhiều lần ở đây chi tiết hơn bất kỳ câu trả lời nào trên trang này, bao gồm unix.stackexchange.com/questions/88811 chỉ dành cho người mới bắt đầu.
JdeBP

1
Lưu ý rằng vi -b, \rdù sao cũng là phần mở rộng vim. không phải POSIX, không phải ở nvi, elvis, Solaris vi ...
Stéphane Chazelas

10

Điều này là do tập lệnh đã được lưu bởi một trình soạn thảo sử dụng các kết thúc dòng của DOS (chẳng hạn như Notepad ++ chẳng hạn). Bạn sẽ phải loại bỏ chúng khỏi tập lệnh của bạn.

Để làm điều này, sử dụng dos2unixtrên tệp script hoặc

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

(điều này sẽ loại bỏ tất cả lợi nhuận vận chuyển từ bất kỳ nơi nào trong tập lệnh)


Đối với mã trong tập lệnh:

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

Cái này có thể trông giống như

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

Điều này loại bỏ các tập tin 1.txttừ thư mục hiện tại, nếu nó tồn tại. Các :lệnh không làm gì (hầu như) và có thể được gỡ bỏ. Các itergiá trị của biến nên được sử dụng như $iter, và được trích dẫn. Và sau đó tôi có thể rõ ràng hơn nhu cầu bằng cách sử dụng ./để nói rằng tập tin cần phải được tìm thấy trong thư mục hiện tại.

Nếu bạn đang lập kế hoạch để tắt chức năng này vào một vòng lặp (ở đây, xóa tất cả các 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

Hoặc, nếu chúng ta cảm thấy lén lút / lười biếng,

rm -f {1..10}.txt

trong vỏ hiểu được mở rộng niềng răng.


3
Notepad ++ thực sự có tùy chọn để sử dụng ngắt dòng Windows / Mac / Linux. Bạn chỉ cần vào menu Chỉnh sửa và sau đó Chuyển đổi EOL-> Unix (LF). Hoặc bạn chỉ có thể nhấp đúp vào góc dưới bên phải nơi nó nói Windows (CR LF)và thay đổi nó thànhUnix (LF)
jesse_b

Cảm ơn tất cả mọi người đã hướng dẫn của bạn. Tôi muốn làm rõ: "iter = 1" là một bộ đếm mà tôi sử dụng sau này cho mục tiêu chính của mình, ngoài dòng 5.
TPham

@TPham Bạn được chào đón. Tôi đã chán và lấy mã của bạn và để cho tâm trí của tôi chạy ấn tượng với nó.
Kusalananda

Hoặc rm -f [1-9].txt 10.txt. Nhưng đó không phải là hoàn toàn hợp lý tương đương, như nếu không có file 1-9 nhưng có một tập tin theo nghĩa đen được gọi là [1-9].txtsau đó nó sẽ bị xóa. : D
Wildcard

5

Kịch bản của bạn có kết thúc dòng sai. Windows sử dụng CR + LF (\ r \ n), Unix sử dụng LF (\ n) và MacOS cổ điển sử dụng CR (\ r). Bạn sẽ cần thay đổi kết thúc dòng trên tất cả các tệp bị ảnh hưởng, bằng trình chỉnh sửa văn bản hoặc công cụ độc lập như dos2unix.

Các hệ thống kiểm soát phiên bản và FTP như SVN có xu hướng có thể chuyển đổi các đầu cuối dòng một cách thích hợp, vì vậy bạn có thể muốn xem xét các tùy chọn đó để truyền tệp trong tương lai.

Nếu các tệp này không được chuyển, nhưng chỉ được sử dụng trên một máy, thì bạn sẽ muốn tìm cài đặt cho các kết thúc dòng trong trình soạn thảo văn bản ưa thích của mình. Hầu hết được quảng cáo là "dành cho lập trình viên" sẽ có tùy chọn như vậy.


Cảm ơn tất cả mọi người vì sự chỉ dẫn hữu ích của bạn. Tôi mới dùng thử dos2unix nhưng có vẻ như tôi không có. Sẽ tìm kiếm và thử lại.
TPham

3

Là một câu trả lời bổ sung, hãy để tôi thêm một vài ghi chú / mẹo ...

Đầu tiên, đối với các tệp văn bản thông thường, bạn có thể dễ dàng xác định xem chúng có kết thúc dòng Unix hoặc DOS hay không bằng cách sử dụng filelệnh. Ví dụ:

$ 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

Lưu ý sử dụng của tôi dos2unix. Tôi rất khuyên bạn nên cài đặt nó. Tùy thuộc vào cách bạn sử dụng Cygwin, bạn có thể thấy bạn cần thực hiện chuyển đổi này thường xuyên đủ để thuận tiện được chào đón. Quan trọng hơn, không có cơ hội lỗi như bạn nhận được với các chỉnh sửa thủ công được thảo luận ở đây.

Để cài đặt bắt đầu thực thi Cygwin chính. Đó là cái có tên như setup-x86_64.exe hoặc một cái gì đó dọc theo những dòng đó. Hãy chắc chắn rằng bạn nhìn thấy một màn hình như thế này:

nhập mô tả hình ảnh ở đây

Vì bạn đã thực hiện cài đặt chính, bạn có thể nhấp vào Tiếp theo cho đến khi bạn nhận được màn hình lựa chọn. Chọn Full trong danh sách thả xuống và nhập "dos2" vào hộp tìm kiếm và chọn công cụ như hiển thị ở đây:

nhập mô tả hình ảnh ở đây

Sau đó bấm Next lần nữa và để cài đặt hoàn tất. Đó là nó. Chúc vui vẻ. Cygwin, ngoại trừ sự bất tiện thường xuyên này, là một gói tuyệt vời.


Cảm ơn bạn rất nhiều vì lớp B hướng dẫn của bạn! Nhóm Stack Exchange này rất hữu ích. Tôi thực sự đánh giá cao sự hỗ trợ này.
TPham

1

Nếu không phải dos2unix, thì cũng có 'lật'

$ flip -u yourfilename.txt

sẽ lật nó để sử dụng kết thúc dòng unix.


1

Tôi sử dụng Notepad ++ để chỉnh sửa tập lệnh bash (.sh) của mình bằng cách kết nối với máy chủ bằng WinSCP
(Để thiết lập trình chỉnh sửa WinSCP thành Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Điều này rất thiết thực để mở tệp từ máy chủ để chỉnh sửa / lưu thay vì trình chỉnh sửa " Vim ".
Khi bạn mở tệp trong Notepad ++ , bấm đúp vào cột thứ 7 ở thanh trạng thái ở dưới cùng và chọn " Unix (LF) ".

nhập mô tả hình ảnh ở đây

Ngoài ra, bạn phải thay đổi cái thứ 8 bằng cách Mã hóa -> Mã hóa bằng UTF-8 ở thanh trên cùng.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.