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

あなたの場合、問題は行の連続にあるのではなく、2番目のパラメータに二重引用符をエスケープせずに使用しているという事実にあります(@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部分は「閉じる」二重引用符の直後にあるため、まだ2番目のタグの一部と見なされます。)
  • Doe and i want to limit this line to 80 columnsDoe2番目のパラメータと同じ理由で3番目のパラメータに追加)John

ただし、関数はlog_message最初の2つの引数のみを解釈するため、残りの文字列フラグメントは失われます。

答え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では、他のほとんどの言語とは異なり、引数の拡張や引用符を除いて、シェルの特殊文字を中心に回転します。結局、その部分は引用されていないまま残され"...."${var}"..."ます${var}。つまり、分割+グローブを経るという意味です!

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

選択です。これらの行の連続(次に\改行文字が続く)は、二重引用符の内側または外側またはhere文書で使用できますが、単一引用符内または引用符区切り文字を含むhere文書では使用できません。

これにより、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.

関連情報