如何在 bash 脚本中正确换行和连接字符串

如何在 bash 脚本中正确换行和连接字符串

我有一个 Bash 脚本,具有记录带有时间和状态的消息的功能,并且我只想保留我的脚本 80 列:

#!/bin/bash

log_message() {
  echo "[$(date)]-[$1] : $2" >> log.txt
}

varName="John Doe"

# line break to not exceed 80 columns
log_message "WARNING" "I am "${varName}" and i want to limit this line \
to 80 columns"

日志文件中的结果不符合预期:

[Fri Jun 24 13:50:12 CEST 2022]-[WARNING] : I am John

在 Bash 中执行此操作的正确方法是什么?

答案1

在您的情况下,问题不在于行继续,而在于您在双引号第二个参数中使用了双引号而不转义它们(请注意,看到@Stéphane 的答案,可能您实际上是有意这样做的 - 请参阅下文了解为什么这不是一个好主意)。尝试一下

log_message "WARNING" "I am \"${varName}\" and i want to limit this line \
to 80 columns"

使用之前未转义的引号${varName},变量引用现在实际上是外部双引号和分词,因此log_message调用会看到以下参数:

  • WARNING
  • I am John(该John部分仍将被视为第二个标记的一部分,因为它紧跟在“结束”双引号之后)
  • Doe and i want to limit this line to 80 columns(出于与第二个参数Doe相同的原因附加到第三个参数)John

但是,您的函数log_message仅解释前两个参数,因此剩余的字符串片段会丢失。

答案2

仅供参考,可以写更好的log_messagebash

exec {logfd}>> log.txt
log_message() {
  local severity="$1" message
  shift
  for message do
    printf '[%(%FT%T%z)T]-[%s] : %s\n' -1 "$severity" "$message" >&"$logfd"
  done
}

这避免了date每次运行一个命令并重新打开日志文件,并允许您传递多条消息(每条消息显示在单独的行上)。

然后用于\行延续,如 @AdminBee 已经提到的。请注意,在 sh/bash 中,与大多数其他语言相反,它围绕参数扩展或对 shell 来说是特殊的字符,除了引号之外。你"...."${var}"..."最终留下了${var}未加引号的部分,这意味着它经历了 split+glob!

log_message WARNIN\
G "I am ${varName}\
 and I want to lim\
it this line to 20\
 columns"

是一个选择。请注意这样的行延续(后跟\换行符),可以在双引号内部或外部或此处文档中使用,但不能在单引号内或带有引号分隔符的此处文档中使用。

有了这个log_message,你还可以这样做:

log_message WARNING \
  "I am ${varName}" \
  'and I want to limit' \
  'the length of the lines' \
  'in the log file.'

进入log.txt

[2022-06-24T13:28:46+0100]-[WARNING] : I am John Doe
[2022-06-24T13:28:46+0100]-[WARNING] : and I want to limit
[2022-06-24T13:28:46+0100]-[WARNING] : the length of the lines
[2022-06-24T13:28:46+0100]-[WARNING] : in the log file.

相关内容