寻找跨GNU/Linux与macOS的Bash无重定向追加字符串至文件方案
跨平台Bash debug函数的STDIN兼容问题
需求与现有实现
我编写了一个Bash的debug()函数,目标是:
- 可在GNU Linux与macOS间跨平台运行
- 能在
while ...; do ...; done < foo这类重定向循环内正常使用 - 将消息写入
/dev/stderr或由$DEBUG_LOG指定的日志文件
现有简化版本代码:
# @description Write debug messages to $DEBUG_LOG if set, else /dev/stderr # @usage debug <message> function debug() { if [[ "${DEBUG}" == "true" ]]; then # Use $DEBUG_LOG if set, else /dev/stderr local log_file="${DEBUG_LOG:-/dev/stderr}" # Join all arguments using \n and prepend every line with "[debug] " local debug_message=$(printf "%s\n" "${@}" | sed 's/^/[debug] /') # Append the debug message to the log file echo "${debug_message}" | dd of="${log_file}" conv=notrunc oflag=append status=none fi }
核心问题
直接使用echo "${debug_message}" >> "${log_file}"不可行:在while ... done < file.txt循环内调用debug foo时,函数内的重定向会消耗STDIN,导致循环中断。
需要一个可通过管道操作、能将内容追加至日志文件或STDERR的命令。dd在GNU Linux上正常,但macOS的BSD版本dd不支持oflag=append参数,无法跨平台使用。
理想方案
希望有类似append-stuff的内置/标准工具,支持两种无重定向的使用方式:
echo "${debug_message}" | append-stuff "${DEBUG_LOG:-/dev/stderr}" append-stuff "${debug_message}" "${DEBUG_LOG:-/dev/stderr}"
已尝试的方法
测试用消息:
debug_message=$'hello world\nsome |[]& weird ch4r4ct3r$!\nfoo bar'
sed
尝试多种变体均失败:
sed -e '$a '"${debug_message}" "${DEBUG_LOG:-/dev/stderr}" # 报错:sed: -e expression #1, char 42: unterminated `s' command sed -e '$a helloworld' /dev/stderr # 进程挂起 echo "${debug_message}" | sed -e '$r /dev/stdin' "${DEBUG_LOG:-/dev/stderr}" # 进程挂起
awk -i inplace
尝试echo "${debug_message}" | awk -i inplace ... /dev/stdin ... /dev/stderr的多种变体,要么出现警告、要么导致shell挂起,且inplace扩展并非跨平台内置功能。
dd
echo "${debug_message}" \ | dd of="${DEBUG_LOG:-/dev/stderr}" conv=notrunc oflag=append status=none # GNU Linux可用,但macOS不支持oflag=append,BSD版dd无等效参数
目前不清楚是否存在符合需求的append-stuff类命令(内置于Bash或属于*nix标准工具集),求告知。
内容的提问来源于stack exchange,提问作者Shaun Mitchell
相关产品推荐
相关产品推荐

