Почему я получаю строку 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  

Может кто-нибудь объяснить, как я могу обойти эту проблему?

TPham
источник

Ответы:

28

У вас есть конец строки в стиле Windows.

Команда no-op :вместо этого читается как :<carriage return>, отображается как :\rили более полно как $':\r'.

Беги dos2unix scriptnameи у тебя все будет хорошо.


Если у вас нет dos2unix, следующее должно работать почти везде (и я тестировал на MobaXterm на Windows):

vi -b filename

Затем viвведите:

:%s/\r$//
:x

Тебе хорошо идти.


В vim, что вы используете в Cygwin vi, есть несколько способов сделать это. Другой включает fileformatнастройку, которая может принимать значения dosили unix. Либо явно измените его после загрузки файла с

set fileformat = unix
или явно форсировать формат файла при записи файла с

: w + fileformat = unix

Подробнее об этом см. Здесь множество вопросов и ответов по этой теме, в том числе:

Wildcard
источник
Просто хочу уточнить, "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 ...
Стефан
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 Не за что. Мне было просто скучно, я взяла твой код и позволила моему разуму работать с ним в духе импрессионизма.
Кусалананда
Или 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 или что-то в этом роде. Убедитесь, что вы видите такой экран:

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

Поскольку вы уже выполнили первичную установку, вы сможете нажимать Далее до тех пор, пока не появится экран выбора. Выберите Full в раскрывающемся списке и введите «dos2» в поле поиска и выберите инструмент, как показано здесь:

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

Затем нажмите Next еще раз и позвольте установке завершиться. Вот и все. Веселиться. Cygwin, за исключением этого случайного неудобства, является отличным пакетом.

B слой
источник
Большое спасибо за вашу инструкцию B Layer! Эта группа обмена стека очень полезна. Я действительно ценю эту поддержку.
TPham
1

Если не dos2unix, есть также 'flip'

$ flip -u yourfilename.txt

перевернем его, используя окончания концов Unix.

Chai
источник
1

Я использую Notepad ++ для редактирования сценариев bash (.sh), подключившись к серверу с помощью WinSCP
(чтобы настроить редактор WinSCP на Notepad ++: https://winscp.net/rus/docs/ui_editor_preferences )

Это очень удобно для открытия файлов с серверов для редактирования / сохранения вместо редактора « Vim ».
Когда вы открываете файл в Notepad ++ , дважды щелкните по 7-му столбцу в строке состояния внизу и выберите « Unix (LF) ».

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

Кроме того, вы должны изменить восьмой путем кодирования -> кодировать в UTF-8 в верхней панели.

Альпер т. Turker
источник
0

Вам не нужно менять фактическую строковую кодировку файла, чтобы Cygwin's Bash успешно работал с кодировками конца строки Mac и Windows. Есть вариант, который вам просто нужно включить.

Просто обновите ваш, ~/.bash_profileчтобы он содержал

export SHELLOPTS
set -o igncr

См. Https://ptolemy.berkeley.edu/projects/chess/softdevel/faq/5.html.

swdev
источник