我想编写一个简单的函数来查找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安装)上运行。两者都给出了相同的结果。
在循环播放时,我需要做什么才能包含换行符?
答案 0 :(得分:3)
将{'1}}的读取选项-n
替换为<{1}}。
答案 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