Как передать `dos2unix` в` while read` в bash? - PullRequest
0 голосов
/ 06 октября 2018

Сейчас я пытаюсь исправить проблему в моем скрипте PrintBans.sh .

Проблема в том, что программа, которая генерирует этот файл, сохраняет его с помощью \ r \ nокончания строк, поэтому мне нужен цикл while, чтобы иметь возможность читать \ r \ n строк, в противном случае в конце последней строки есть дополнительный \ r, что приводит к сбою арифметики:

 - 621355968000000000")syntax error: invalid arithmetic operator (error token is "

Я пробовал это.

while read ban
do
    ...
done < dos2unix $file

while read ban
do
    ...
done < `dos2unix $file`

cat $file > dos2unix > while read ban
do
    ...
done

while read ban
do
    ...
done < dos2unix < $file

Я также вижу, что некоторые люди устанавливают IFS='\r\n', но у меня это не сработало.

Разве невозможно передавать файлы через dos2unix безперезаписать исходный файл?

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

Учитывая контекст вашего скрипта на github, предполагая, что ни одно из полей вашего CSV-файла не содержит символ CR, вам просто нужно поставить CR в IFS.

Изменение:

while read ban; do ...

до:

while IFS=$'\r' read -r ban; do ...

За ту же цену вы можете получить разделение бана на шесть полей с помощью:

while IFS=$';\r' read -r name idip end_time reason admin start_time remaining; do
    name=${name/,/\\,}
    ticksToDateString "$end_time"
    ...
0 голосов
/ 06 октября 2018

Литеральный ответ: Pipe Through!

Если вы не сообщите dos2unix имя файла, с которым он работает, он не сможет изменить этот файл на месте.

while IFS= read -r line; do
  echo "No carriage returns here: <$line>"
done < <(dos2unix <"$file")

Перенаправления выполняются оболочкой до запуска программы. Когда вы вызываете dos2unix <input.txt, оболочка заменяет дескриптор файла 0 дескриптором чтения на input.txt перед вызовом dos2unix без аргументов.

Если вы хотите быть действительно параноиком (и заплатить за производительность за эту паранойю), вы можете предотвратить гипотетическое несуществующее dos2unix, которое изменило файловый дескриптор, полученный на stdin ввместо этого сделайте его <(cat <"$file" | dos2unix) таким, чтобы dos2unix считывал данные из FIFO, подключенного к отдельному исполняемому файлу cat, а не прямо из входного файла.Само собой разумеется, я никогда не советую это на практике.


Лучший ответ: Не

Вам не нужно dos2unix (что -со стандартным поведением модификации на месте - предназначено для интерактивных пользователей, а не для сценариев);сама оболочка может отбрасывать для вас возврат каретки:

#!/usr/bin/env bash
#              ^^^^- not /bin/sh; needed for $'' syntax and [[ ]]

while IFS= read -r line || [[ $line ]]; do
  line=${line%$'\r'}
  echo "No carriage returns here: <$line>"
done <"$file"
  • ${var%expr} - это расширение параметра , которое удаляет любой конечный экземпляр выражения glob expr из содержимогопеременной var.
  • $'\r' - это ANSI C-подобная строка синтаксис для возврата каретки.Использование этого синтаксиса важно, потому что другие вещи, которые выглядят так, как будто они могут ссылаться на возврат каретки не .

    • \r вне контекста цитирования любого вида, - это простобуква r.
    • "\r" или '\r' - это два символа (обратная косая черта, а затем буква r), а не возврат каретки.
  • [[ $line ]] - расширение ksh, принятое bash, эквивалентное [ -n "$line" ];он проверяет, является ли переменная line непустой.read может возвращать false при заполнении строки, если у вас есть частичная строка без какого-либо ограничителя;как указывает l0b0, линейные разделители вместо терминаторы являются общими для Windows.Это обеспечивает обработку последней строки файла, даже если она не заканчивается новой строкой.
...