如何在bash中将`dos2unix`传递到`while read`中?

时间:2018-10-06 20:07:16

标签: bash dos2unix

现在,我正在尝试解决my PrintBans.sh script中的问题。

问题是,生成该文件的程序将其保存为\ 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 :(得分:5)

书面答案:直通!

如果您不告诉dos2unix正在使用的文件的名称,它将无法就地修改该文件。

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

重定向是在启动程序之前由外壳程序 执行的,当您调用dos2unix <input.txt时,外壳程序将在调用{之前用input.txt上的读取句柄替换文件描述符0。 {1}},不带参数。

如果您想真正成为偏执偏执狂(并为该偏执狂付出性能成本),则可以防止假设的不存在的dos2unix修改了从stdin就地接收到的文件描述符通过将其设置为dos2unix,以使<(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" parameter expansion,它从变量${var%expr}的内容中删除了全局表达式expr的所有尾随实例。
  • varANSI C-like string的回车语法。使用该语法非常重要,因为看起来像其他东西的东西可能引用了回车符不要

    • $'\r'只是任何形式的引用上下文之外的字母\r
    • r"\r"是两个字符(反斜杠,然后是字母'\r'),而不是单个回车符。
  • r是bash等效于[[ $line ]]的ksh扩展;它检查变量[ -n "$line" ]是否为非空。如果您的分行没有任何终止符,则line可能会返回false,同时仍然填充行;正如l0b0所指出的,在Windows中,行分隔符而不是终止符很常见。这样可以确保处理文件的最后一行,即使它没有以换行结尾。

答案 1 :(得分:0)

考虑到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"
    ...