Чому я отримую "рядок 1: $ ': \ r': команда не знайдена"?


13

Я використовував Cygwin на своєму ноутбуці (DOS). У мене є колекція сценаріїв від колег, і моя власна. Я не ІТ-людина, не обізнаний в Unix. Я дотримуюся синтаксису своїх колег і вмію керувати кількома простими речами.

Сценарії добре працювали на моєму старому ноутбуці. Я щойно змінив ноутбук, встановив Cygwin. Коли я запускаю свої сценарії, вони не працюють. Ось один приклад повідомлення про помилку, яке я отримую:

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

Ось топ-5 рядків мого сценарію

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

Чи можете мені хтось пояснити, як я можу обійти цю проблему?

Відповіді:


29

У вас є закінчення у стилі Windows.

Команда без операції :читається як :<carriage return>, відображається як :\rабо більш повно як $':\r'.

Біжи, dos2unix scriptnameі тобі все буде добре.


Якщо у вас немає dos2unix, наступне має працювати майже де завгодно (і я тестував MobaXterm в Windows):

vi -b filename

Потім viвведіть:

:%s/\r$//
:x

Ти добре підеш.


Для того vim, для чого ви користуєтесь Cygwin vi, існує кілька способів цього зробити. Інший включає fileformatналаштування, яке може приймати значення dosабо unix. Або явно змінити його після завантаження файлу

встановити fileformat = unix
або явно форсувати формат файлу при написанні файлу за допомогою

: w + fileformat = unix

Детальніше про це див. Тут багато питань та відповідей, що висвітлюють цю тему, включаючи:


Просто хочу уточнити, що "iter = 1" - це мій лічильник, який буде використовуватися для кількості раундів математичного алгоритму, які моя модель повинна буде повторити пізніше за межею 5. Я щойно розмістив 5 перших рядків, щоб перейти до повідомлення про помилку. Всі коментарі та інструкції дуже вдячні !!
TPham

Я просто спробував запропоновану команду "$ tr -d .....", але в моєму ноутбуці щось не так. Він не повертається до "$", але на екрані з'являється ">". Я маю використовувати contrl C, щоб вийти. Потім я перевірив сценарій, щоб перевірити, чи проблема виправлена, але вона все ще існує. Вибачте, мої знання в цій галузі дуже мінімальні! Я намагаюся використовувати свою колекцію сценаріїв, оскільки вони дуже допомагають моїй роботі. Дякую всім за терплячість та корисність для мене.
TPham

@TPham, див. Редагування. Якщо це працює, обов'язково використовуйте галочку біля відповіді, щоб "прийняти" її. (Прийміть, яка відповідь найкраще вирішить вашу проблему.) Unix.stackexchange.com/help/someone-answers
Wildcard

1
Команди, які є словами, насправді не є складнішим для новачка, ніж таємничий заклик, який є майже цілком пунктуаційним. На це не потрібна окрема відповідь. Просто потрібна ця відповідь, щоб згадати, що це vimможна зробити двома способами, в одному з яких використовуються слова. Або, ще краще, вказати на те, де на це підпорядковане завдання тут і далі відповідали набагато більш детально, ніж будь-яка відповідь на цій сторінці, включаючи unix.stackexchange.com/questions/88811 лише для початку.
JdeBP

1
Зверніть увагу , що vi -b, \rє ВІМ розширення в будь-якому випадку. не POSIX, не в nvi, elvis, Solaris vi ...
Stéphane Chazelas

10

Це пов'язано з тим, що сценарій був збережений редактором, який використовує закінчення рядків DOS (наприклад, Notepad ++, наприклад). Вам доведеться видалити їх зі своїх сценаріїв.

Для цього або скористайтеся dos2unixфайлом сценарію, або

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

(це видалить усі повернення перевезення з будь-якого місця в сценарії)


Що стосується коду в сценарії:

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

Це, можливо, має виглядати приблизно так

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

Це видаляє файл 1.txtіз поточного каталогу, якщо він існує. :Команда нічого не робить (майже) і може бути видалена. Значення iterзмінної має використовуватися як $iterкотирування. І тоді я, можливо, явніше, ніж потрібно, ./кажучи про те, що файл потрібно знайти в поточному каталозі.

Якщо ви плануєте , щоб перетворити це в петлю (тут, щоб видалити всі файли 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

Або, якщо ми відчуваємо підлість / лінивий,

rm -f {1..10}.txt

в оболонках, що розуміє розширення дужок.


3
У Notepad ++ фактично є можливість використовувати розриви рядків Windows / Mac / Linux. Вам просто потрібно перейти до меню Правка, а потім EOL Conversion-> Unix (LF). Або ви можете просто двічі клацнути в правому нижньому куті, де написано, Windows (CR LF)і змінити його наUnix (LF)
jesse_b

Дякую всім за вашу інструкцію. Хочеться уточнити: "iter = 1" - це лічильник, який я використовую пізніше для своєї основної мети, поза межами 5.
TPham

@TPham Ласкаво просимо. Мені просто нудно, і я взяв твій код, і дозволити мені міркувати імпресіонізмом.
Kusalananda

Або rm -f [1-9].txt 10.txt. Але це не зовсім логічно еквівалентно, як якщо б не було файлів 1-9, але є файл, буквально названий, [1-9].txtвін буде видалений. : D
Wildcard

5

Ваші сценарії мають неправильні закінчення рядків. Windows використовує CR + LF (\ r \ n), Unix використовує LF (\ n), а Classic MacOS використовує CR (\ r). Вам потрібно буде змінити закінчення рядків для всіх файлів, на які вони впливають, або за допомогою текстового редактора або окремого інструмента, як-от dos2unix.

Системи контролю FTP та версій, такі як SVN, як правило, зможуть належним чином перетворити закінчення рядків, тому ви, можливо, захочете вивчити ці варіанти передачі файлів у майбутньому.

Якщо ці файли не передаються, а просто використовуються на одній машині, вам потрібно буде знайти налаштування для закінчень рядків у бажаному текстовому редакторі. Більшість, які рекламуються як "для програмістів", матимуть такий варіант.


Дякую всім за корисну інструкцію. Я просто спробував dos2unix, але, здається, у мене його немає. Буде шукати та спробувати ще раз.
TPham

3

В якості додаткової відповіді дозвольте додати пару зауважень / підказок ...

По-перше, для звичайних текстових файлів ви можете легко визначити, чи мають вони рядок Unix або DOS, що закінчується fileкомандою. Наприклад:

$ 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

Зверніть увагу на моє використання dos2unix. Настійно рекомендую встановити його. Залежно від способу використання Cygwin, можливо, вам доведеться робити це перетворення досить часто, щоб зручність була бажаною. Що ще важливіше, немає шансів на помилку, як ви отримаєте з наведеними тут ручними правками.

Щоб встановити, запустіть основний виконуваний файл Cygwin. Це той із назвою, як setup-x86_64.exe або щось подібне. Переконайтеся, що ви бачите такий екран:

введіть тут опис зображення

Оскільки ви вже зробили первинну установку, ви повинні мати можливість натиснути Далі весь шлях, поки не з'явиться екран вибору. Виберіть Повне у спадному меню та введіть "dos2" у вікні пошуку та виберіть інструмент, як показано тут:

введіть тут опис зображення

Потім натисніть кнопку Далі ще раз і нехай установка завершиться. Це воно. Весело. Cygwin, за винятком випадкових незручностей, - це приголомшливий пакет.


Дуже дякую за вашу інструкцію B Layer! Ця група обміну стеками дуже корисна. Я дуже ціную цю підтримку.
TPham

1

Якщо не dos2unix, є також "flip"

$ flip -u yourfilename.txt

переверне його до використання закінчень ліній Unix.


1

Я використовую Notepad ++ для редагування моїх скриптів bash (.sh) шляхом підключення до сервера WinSCP
(Щоб налаштувати редактор WinSCP до Notepad ++: https://winscp.net/eng/docs/ui_editor_preferences )

Це дуже практично для відкриття файлів із серверів для редагування / збереження замість редактора " Vim ".
Коли ви відкриєте файл у « Блокноті ++» , двічі клацніть 7-й стовпець у рядку стану внизу та виберіть « Unix (LF) ».

введіть тут опис зображення

Крім того, вам потрібно змінити восьмий за допомогою Encoding -> Encode in UTF-8 у верхній панелі.


0

Вам не потрібно міняти фактичне кодування рядків файлів, щоб Cygwin's Bash із задоволенням працював з кодами Mac та Windows кінця лінії. Є варіант, який потрібно просто перевернути.

Просто оновіть свою, ~/.bash_profileщоб вона містила

export SHELLOPTS
set -o igncr

Дивіться https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.