Команда Windows для преобразования окончаний строки Unix?
Есть ли команда Windows для преобразования окончаний строк файла?
У нас есть test.bat , который нам нужно запустить, чтобы запустить наш сервер. Мы используем Perforce, и нам нужно иметь окончание строк unix в нашей рабочей области. По какой-то причине нам не разрешено изменять окончания строк для Windows в наших рабочих пространствах. Однако сервер работает в Windows.
Каждый раз, когда я должен запускать bat файл, я открываю его в Notepad ++ и выбираю Edit → EOL conversion → Windows. Есть ли способ автоматизировать это, так что нам не нужно вручную изменять окончание строки каждый раз, когда мы синхронизируемся с Perforce?
Это можно сделать очень легко с помощью команды more , которая включена в Windows NT и более поздних версиях. Чтобы преобразовать input_filename , который содержит UNIX EOL (конец строки) \n – output_filename , который содержит Windows EOL \r\n , просто выполните следующее:
Команда more имеет дополнительные параметры форматирования, о которых вы, возможно, и не подозреваете. Запустите more/? , чтобы узнать, что еще может сделать more .
Используйте утилиту unix2dos. Вы можете скачать бинарные файлы здесь.
Вы можете сделать это без дополнительных инструментов в VBScript:
Поместите вышеуказанные строки в файл unix2dos.vbs и запустите его следующим образом:
Вы также можете сделать это в PowerShell:
который можно было бы еще более упростить:
Вышеуказанный оператор работает без явной замены, потому что Get-Content неявно разбивает входные файлы на любой тип linebreak (CR, LF и CR-LF), а Set-Content объединяет входной массив с разрывами строк Windows (CR- LF) перед записью в файл.
Я имел дело с проблемами CRLF поэтому я решил создать действительно простой инструмент для конвертации (в NodeJS):
Так что если у вас есть NodeJS с установленным npm, вы можете попробовать это:
Путь может быть настроен динамически с помощью регулярного выражения Glob (то же, что и в оболочке).
Так что, если вы можете использовать NodeJS, это действительно просто, и вы можете интегрировать эту команду для преобразования всего рабочего пространства в желаемые окончания строк.
Windows ‘MORE не надежна, она неизбежно разрушает TAB и добавляет строки.
unix2dos также является частью Minig/MSYS, Cygutils, GnuWin32 и других коллекций двоичных портов unix – и может быть уже установлен.
Если python, этот однострочный конвертер преобразует любые окончания строк в текущую платформу – на любой платформе:
Или поместите однострочный вкладыш в .bat/shell script и на PATH в соответствии с вашей платформой:
и используйте этот инструмент, например
Опираясь на TampaHaze и MD XF полезные ответы.
Это изменит все файлы .txt в текущем каталоге с LF на CRLF в командной строке.
Если вы не хотите проверять каждое изменение
Включить подкаталоги изменить
Чтобы сделать все это в пакетном файле, включая подкаталоги, не предлагая использовать ниже
Мой вклад в это, преобразование нескольких файлов в папку:
for %%z in (*.txt) do (for /f «delims=» %%i in (%%z) do @echo %%i)>%%z.tmp
Вы можете создать простой пакет script, чтобы сделать это для вас:
Затем запустите и будет мгновенно преобразован в конец строки DOS.
На основании ответа Endoro, но чтобы сохранить пробелы, попробуйте следующее:
Я клонировал свой проект git, используя git bash на windows . Все файлы имели LF окончания. Наш репозиторий по умолчанию имеет окончания CRLF .
Я удалил проект, а затем снова клонировал его с помощью Windows Command Prompt . Окончания CRLF были тогда целы. В моем случае, если бы я изменил окончание проекта, это привело бы к огромным усилиям и вызвало бы проблемы для моих товарищей по команде. Итак, сделал это так. Надеюсь, это кому-нибудь поможет.
Я беру курс AWS, и мне часто приходилось копировать текстовые поля веб-форм AWS в Блокнот Windows. Таким образом, я получаю текст с разделителями LF только в своем буфере обмена. Я случайно обнаружил, что вставив его в мой редактор Delphi, а затем нажав Ctrl + K + W, мы напишем текст в файл с разделителями CR + LF. (Бьюсь об заклад, многие другие редакторы IDE сделали бы то же самое).
Для преобразования UNIX (LF) в Windows (CR-LF) используйте следующую команду
Если у вас есть bash (например, git bash), вы можете использовать следующий скрипт для конвертации из unix2dos:
аналогично, чтобы конвертировать из dos2unix:
Строки в C# и .NET
От переводчика: Джон Скит написал несколько статей о строках, и данная статья является первой, которую я решил перевести. Дальше планирую перевести статью о конкатенации строк, а потом — о Юникоде в .NET.
Тип System.String (в C# имеющий алиас string) является одним из наиболее часто используемых и важных типов в .NET, и вместе с тем одним из самых недопонимаемых. Эта статья описывает основы данного типа и развенчивает сложившиеся вокруг него мифы и непонимания.
Так что же такое string
Строка в .NET (далее — string, я не буду использовать полное имя System.String каждый раз) является последовательностью символов. Каждый символ является символом Юникода в диапазоне от U+0000 до U+FFFF (будет рассмотрено далее). Строковый тип имеет следующие характеристики:
Строка является ссылочным типом
Существует распространённое заблуждение о том, что строка является значимым типом. Это заблуждение истекает из свойства неизменяемости строки (см. следующий пункт), так как для неискушенного программиста неизменяемость часто по поведению кажется схожей со значимыми типами. Тем не менее, string — ссылочный тип, со всеми присущими ссылочным типам характеристиками. Я более детально расписал о различиях между ссылочными и значимыми типами в своих статьях «Parameter passing in C#» и «Memory in .NET — what goes where».
Строка является неизменяемой
Никак невозможно изменить содержимое созданной строки, по крайней мере в безопасном (safe) коде и без рефлексии. Поэтому вы при изменении строк изменяете не сами строки, а значения переменных, указывающих на строки. Например, код s = s.Replace («foo», «bar»); не изменяет содержимое строки s, которое было до вызова метода Replace — он просто переназначает переменную s на новообразованную строку, которая является копией старой за исключением всех подстрок «foo», заменённых на «bar».
Строка может содержать значение null
В языке C строки являются последовательностями символов, оканчивающимися символом ‘\0‘, также называемым «nul» или «null». Я называю его «null», так как именно такое название имеет символ ‘\0’ в таблице символов Юникода. Не путайте символ «null» с ключевым словом null в C# — тип System.Char является значимым, а потому не может принимать значение null . В .NET строки могут содержать символ «null» в любом месте и работать с ним без каких-либо проблем. Тем не менее, некоторые классы (к примеру, в Windows Forms) могут расценивать «null»-символ в строке как признак конца строки и не учитывать всё содержимое строки после этого символа, поэтому использование «null»-символов таки может стать проблемой.
Строка переопределяет оператор равенства ==
При вызове оператора == для определения равенства двух строк происходит вызов метода Equals , который сравнивает именно содержимое строк, а не равенство ссылок. К примеру, выражение «hello».Substring(0, 4)==»hell» возвратит true , хотя ссылки на строки по обеих сторонах оператора равенства разные (две ссылки ссылаются на два разных строковых экземпляра, которые, при этом, содержат одинаковые значения). Вместе с тем необходимо помнить, что равенство значений, а не ссылок происходит только тогда, когда оба операнда на момент компиляции являются строго строковым типом — оператор равенства не поддерживает полиморфизм. Поэтому если хотя бы один из сравниваемых операндов будет иметь тип object , к примеру (хотя внутренне и будет оставаться строкой), то будет выполнено сравнение ссылок, а не содержимого строк.
Интернирование
В .NET существует понятие «пула интернирования» (intern pool). По своей сути это всего лишь набор строк, но он обеспечивает то, что когда вы в разных местах программы используете разные строки с одним и тем же содержимым, то это содержимое будет храниться лишь один раз, а не создаваться каждый раз по-новому. Вероятно, пул интернирования зависит от конкретного языка, однако он определённо существует в C# и VB.NET, и я бы был очень удивлён, увидев язык на платформе .NET, не использующий пул интернирования; в MSIL пул интернирования очень просто использовать, гораздо проще, нежели не использовать. Наряду с автоматическим интернированием строковых литералов, строки можно интернировать вручную при помощи метода Intern , а также проверять, является ли та или иная строка уже интернированной при помощи метода IsInterned . Метод IsInterned не интуитивен, так как вы ожидаете, что он возвратит Boolean , а вот и нет — если текущая строка уже существует в пуле интернирования, то метод возвратит ссылку на неё, а если не существует, то null . Подобно ему, метод Intern возвращает ссылку на интернированную строку, причём вне зависимости от того, была ли текущая строка в пуле интернирования до вызова метода, или же она была туда занесена вместе с вызовом метода, или же пул интернирования содержит копию текущей строки.
Литералы
Литерал — это, грубо говоря, «захардкодженное» в коде значение строки. Есть два типа строковых литералов в C# — стандартные (regular) и дословные (verbatim). Стандартные литералы в C# схожи с таковыми в большинстве языков программирования — они обрамляются в двойные кавычки («), а также могут содержать специальные символы (собственно двойные кавычки («), обратный слеш (\), перенос строки (carriage return — CR), подача строки (line feed — LF) и некоторые другие), требующие экранирования. Дословные литералы позволяют почти то же самое, что и стандартные, однако дословный литерал оканчивается на первых не продублированных двойных кавычках. Чтобы собственно вставить в дословный литерал двойные кавычки, вам нужно их продублировать («»). Также, в отличие от стандартного литерала, в дословном могут присутствовать символы возврата каретки и переноса строки без экранирования. Для использования дословного литерала необходимо указать @ перед открывающей кавычкой. Ниже в таблице собраны примеры, демонстрирующие различия между описанными типами литералов.
Стандартный литерал | Дословный литерал | Результирующая строка |
---|---|---|
«Hello» | @»Hello» | Hello |
«Обратный слеш: \\» | @»Обратный слеш: \» | Обратный слеш: \ |
«Двойная кавычка: \»» | @»Двойная кавычка: «»» | Двойная кавычка: « |
«CRLF:\r\nПосле CRLF» | @»CRLF: После CRLF» | CRLF: После CRLF |
Имейте ввиду, что стандартный и дословный литералы существуют только для вас и компилятора C#. Как только код скомпилирован, все литералы приводятся к единообразию.
Вот полный список специальных символов, требующих экранирования:
- \’ — одинарная кавычка, используется для объявления литералов типа System.Char
- \» — двойная кавычка, используется для объявления строковых литералов
- \\ — обратный слеш
- \0 — null-символ в Юникоде
- \a — символ Alert (№7)
- \b — символ Backspace (№8)
- \f —смена страницы FORM FEED (№12)
- \n — перевод строки (№10)
- \r — возврат каретки (№13)
- \t — горизонтальная табуляция (№9)
- \v — вертикальная табуляция (№11)
- Uxxxx — символ Юникода с шестнадцатеричным кодом xxxx
- \xn[n][n][n] — символ Юникода с шестнадцатеричным кодом nnnn, версия предыдущего пункта с переменной длиной цифр кода
- \Uxxxxxxxx — символ Юникода с шестнадцатеричным кодом xxxxxxxx, используется для вызова суррогатных пар.
В своей практике я редко использую символы \a, \f, \v, \x и \U.
Строки и отладчик
Довольно часто при просмотре строк в отладчике (используя VS.NET 2002 и VS.NET 2003) люди сталкиваются с проблемами. Ирония в том, что эти проблемы чаще всего создаёт отладчик, пытаясь быть полезным. Иногда он отображает строку в виде стандартного литерала, экранируя обратными слешами все спецсимволы, а иногда он отображает строку в виде дословного литерала, оглавляя её @. Поэтому многие спрашивают, как удалить из строки @, хотя его там фактически нет. Кроме этого, отладчики в некоторых версиях VS.NET не отображают строки с момента первого вхождения null-символа \0, и что ещё хуже, неправильно вычисляют их длины, так как подсчитывают их самостоятельно вместо запроса к управляемому коду. Естественно, всё это из-за того, что отладчики рассматривают \0 как признак окончания строки.
Учитывая такую путаницу, я пришел к выводу, что при отладке подозрительных строк их следует рассматривать множеством способов, дабы исключить все недоразумения. Я предлагаю использовать приведённый ниже метод, который будет печатать содержимое строки в консоль «правильным» способом. В зависимости от того, какое приложение вы разрабатываете, вы можете вместо вывода в консоль записывать строки в лог-файл, отправлять в трассировщики, выводит в модальном Windows-окне и т.д.
Использование памяти и внутренняя структура
В текущей реализации .NET Framework каждая строка занимает 20+(n/2)×4 байт, где n — количество символов в строке или, что одно и то же, её длина. Строковый тип необычен тем, что его фактический размер в байтах изменяется им самим. Насколько я знаю, так могут делать только массивы. По факту, строка — это и есть массив символов, расположенный в памяти, а также число, обозначающее фактический размер массива в памяти, а также число, обозначающее фактическое количество символов в массиве. Как вы уже поняли, длина массива не обязательно равна длине строки, так как строки могут перераспределяться со стороны mscorlib.dll для облегчения их обработки. Так само делает, к примеру, StringBuilder . И хотя для внешнего мира строки неизменяемые, внутри mscorlib они ещё как изменяемые. Таким образом, StringBuilder при создании строки выделяет несколько больший символьный массив, нежели того требует текущий литерал, а потом прибавляет новые символы в созданный массив до тех пор, пока они «влезают». Как только массив заполняется, создаётся новый, ещё больший массив, и в него копируется содержимое из старого. Кроме этого, в числе, обозначающем длину строки, первый бит отведён под специальный флаг, определяющий, содержит ли строка не-ASCII символы или нет. Благодаря этому флагу исполняющая среда в некоторых случаях может проводить дополнительные оптимизации.
Хотя со стороны API строки не являются null-терминированными, внутренне символьные массивы, представляющие строки, являются. А это значит, что строки из .NET могут напрямую передаваться в неуправляемый код безо всякого копирования, предполагая, что при таком взаимодействии строки будут маршаллированы как Юникод.
Кодировки строк
Если вы не знакомы с кодировками символов и Юникодом, пожалуйста, прочтите сначала мою статью о Юникоде (или её перевод на Хабре).
Как я уже сказал вначале статьи, строки всегда хранятся в Юникод-кодировке. Всякие домыслы о Big-5-кодировках или UTF-8-кодировках являются ошибкой (по крайней мере, по отношению к .NET) и являются следствием незнания самих кодировок или того, как .NET обрабатывает строки. Очень важно понять этот момент — рассматривание строки как такой, которая содержит некий валидный текст в кодировке, отличной от Юникода, почти всегда является ошибкой.
Далее, набор символов, поддерживаемых Юникодом (одним из недостатков Юникода является то, что один термин используется для разных вещей, включая кодировки и схемы кодировок символов), превышает 65536 символов. А это значит, что один char (System.Char) не может содержать любой символ Юникода. А это приводит к понятию суррогатных пар, где символы с кодом выше U+FFFF представляются в виде двух символов. По сути, строки в .NET используют кодировку UTF-16. Возможно, большинству разработчиков и не нужно углубляться касательно этого в детали, но по крайней мере это стоит знать.
Региональные и интернациональные странности
Некоторые странности в Юникоде ведут к странностям при работе со строками и символами. Большинство строковых методов зависимы от региональных настроек (являются culture-sensitive — регионально-чувствительными), — другими словами, работа методов зависит от региональных настроек потока, в котором эти методы выполняются. Например, как вы думаете, что возвратит этот метод «i».toUpper() ? Большинство скажут: «I», а вот и нет! Для турецких региональных настроек метод вернёт «İ» (код U+0130, описание символа: «Latin capital I with dot above»). Для выполнения регионально-независимой смены регистра вы можете использовать свойство CultureInfo.InvariantCulture и передать его как параметр в перегруженную версию метода String.ToUpper , которая принимает CultureInfo .
Есть и другие странности, связанные со сравнением и сортировкой строк, а также с нахождением индекса подстроки в строке. Некоторые из этих операций регионально-зависимы, а некоторые — нет. Например, для всех регионов (насколько я могу видеть) литералы «lassen» и «la\u00dfen» (во втором литерале шестнадцатеричным кодом указан символ «S острое» или «эсце́т») определяются как равные при передачи их в методы CompareTo или Compare , но вот если передать их в Equals , то будет определено неравенство. Метод IndexOf будет учитывать эсцет как «ss» (двойное «s»), но вот если вы используете одну из перегрузок CompareInfo.IndexOf , где укажете CompareOptions.Ordinal , то эсцет будет обработан правильно.
Некоторые символы Юникода вообще абсолютно невидимы для стандартного метода IndexOf . Однажды кто-то спросил в группе новостей C#, почему метод поиска и замены уходит в бесконечный цикл. Этот человек использовал метод Replace для замены всех сдвоенных пробелов одним, а потом проверял, окончилась ли замена и нет ли больше сдвоенных пробелов в строке, используя IndexOf . Если IndexOf показывал, что сдвоенные пробелы есть, строка снова отправлялась на обработку к Replace . К сожалению, всё это «ломалось», так как в строке присутствовал некий «неправильный» символ, расположенный точно между двумя пробелами. IndexOf сообщал о присутствии сдвоенного пробела, игнорируя этот символ, а Replace не выполнял замену, так как «видел» символ. Я так и не узнал, что это был за символ, но подобная ситуация легко воспроизводится при помощи символа U+200C, который является «не-связующим символом нулевой ширины» (англ. zero-width non-joiner character), что бы это не значило, чёрт возьми! Поместите такой или ему подобный в вашу строку, и IndexOf будет его игнорировать, а Replace — нет. Снова-таки, чтобы заставить оба метода работать одинаково, вы можете использовать CompareInfo.IndexOf и указать ему CompareOptions.Ordinal . Мне кажется, что уже написано достаточно много кода, который будет «валиться» на таких «неудобных» данных. И я даже не намекаю, что мой собственный код застрахован от подобного.
Microsoft опубликовала некоторые рекомендации касательно обработки строк, и хотя они датируются 2005-м годом, их всё ещё сто́ит прочесть.