通过 bash 将字符串附加到文件而无需重定向的内置/便携式方法

问题描述 投票:0回答:1

我有一个用 bash 编写的

debug()
函数,其目的是:

  1. 可跨 GNU Linux 盒子和 MacOS 移植
  2. 可在循环内使用,例如使用重定向的
    while ...; do ...; done < foo
  3. 将消息写入
  4. /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}"

不是一个选择。它在场景 #2 上失败。当在 
debug foo
 循环内调用 
while ... done < file.txt
 时,在 
debug()
 函数内使用重定向将吃掉 STDIN 并中断循环。

从那以后,我确定我需要一些命令,我可以用

pipe 代替并附加到日志文件或 STDERR,并且 dd

 工作得很好,直到我尝试在 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 # hangs echo "${debug_message}" | sed -e '$r /dev/stdin' "${DEBUG_LOG:-/dev/stderr}" # hangs
awk -i 就地

我玩过

echo "${debug_message}" | awk -i inplace ... /dev/stdin ... /dev/stderr

 的几种不同变体,但它们要么打印警告,要么挂起外壳。更重要的是,就地扩展似乎不是内置/便携式的。

dd

echo "${debug_message}" \ | dd of="${DEBUG_LOG:-/dev/stderr}" conv=notrunc oflag=append status=none # works, but oflag=append is not available on MacOS, and there doesn't seem # to be an equivalent flag in the BSD version of dd


我不知道是否有合适的

append-stuff

 类型的命令,就像我正在寻找的那样,它要么内置于 bash,要么是人们可以合理地期望在任何机器上找到的 *nix 工具标准套件的一部分,但是如果这里有人知道这样的事情,我将非常感激😄

linux bash macos io freebsd
1个回答
0
投票
用你自己的例子

#! /bin/bash # @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 echo "${debug_message}" >> "${log_file}" fi } DEBUG=true DEBUG_LOG=$(mktemp) yes | head -5 > foo i=5 while (( i > 0 )); do debug "$i" read f printf '%s\n' "$f" (( i-- )) done < foo cat "$DEBUG_LOG" rm "$DEBUG_LOG"
您将看到调试消息

[debug] 5 [debug] 4 [debug] 3 [debug] 2 [debug] 1
打印。

© www.soinside.com 2019 - 2024. All rights reserved.