逐个字符读取输入似乎正在跳过换行符

时间:2015-07-19 18:38:37

标签: macos bash shell

我想编写一个简单的函数来查找Bash中输入字符串中的所有换行符,这就是我想出的:

find_newlines() {
  while IFS= read -r -n 1 c; do
    if [[ "$c" == $'\n' ]]; then
      echo 'FOUND NEWLINE'
    fi
  done
}

我以为我做了我需要的一切。我将IFS设置为空,我传递了-r标记,并强制read一次使用-n 1读取一个字符。然而,令我沮丧的是,以下什么都没有做到:

test_data="this is a
test"

printf "$test_data" | find_newlines

我没有收到任何输出。我在Mac OS X下测试,我在Bash版本3.2.57(Apple提供的)和4.3.33(通过Homebrew安装)上运行。两者都给出了相同的结果。

在循环播放时,我需要做什么才能包含换行符?

3 个答案:

答案 0 :(得分:3)

将{'1}}的读取选项-n替换为<{1}}。

请参阅:https://unix.stackexchange.com/a/27424/74329

答案 1 :(得分:2)

这里的问题是read即使在-n 1模式下仍然在读取分隔线。因此,当它看到换行符时,它仍然认为是行分隔符并将其删除(并留下一个空变量)。

$ find_newlines() {
    while IFS= read -r -n 1 c; do
        declare -p c;
    done
}
$ printf 'a\nb' | find_newlines
declare -- c="a"
declare -- c=""
declare -- c="b"

如Cyrus对bash 4.1 + ref的回答所示,您可以使用-N标记read来避免此问题。< / p>

-N选项记录为(来自read的Bash参考手册):

  

-N nchars

     

读取完全nchars字符后返回,而不是等待完整的输入行,除非遇到EOF或读取超时。输入中遇到的分隔符不会被特殊处理,并且在读取nchars字符之前不会导致读取。

对于非4.1 +版本的bash(看起来是2.04+),您可以使用-d标记read指定备用分隔符来解决此问题。输入中不存在的任何分隔符都可以使用。对于许多输入流而言,最可能的值可能是NUL / \0字符,您可以将其指定为read -d ''

$ find_newlines() {
    while IFS= read -d '' -r -n 1 c; do
        declare -p c;
    done
}
$ printf 'a\nb' | find_newlines
declare -- c="a"
declare -- c="
"
declare -- c="b"

答案 2 :(得分:0)

也许您可以使用sed将换行符替换为可以在以后跟踪的某个唯一符号。这将无视bash版本。

enter code here

sed&#39;:a; N; $!ba; s / \ n / @ / g&#39; &LT;&LT;&LT; &#34; BLA

BLA

BLA&#34;

BLA @ BLA @ BLA