提取多行字符串的最后一行

提取多行字符串的最后一行

的输出exif看起来像这样:

ExifMnoteCanon: Loading entry 0xcf27 ('(null)')...
ExifMnoteCanon: Loading entry 0x3ca8 ('(null)')...
ExifMnoteCanon: Loading entry 0xf88a ('(null)')...
2013:08:22 18:01:16

在我的 bash 脚本中,我将其存储在一个变量中:

datetime="$(exif --debug --machine-readable --tag=DateTimeOriginal "$file" 2>&1)"

我想使用 bash 参数替换来提取最后一行。我认为这会起作用:

datetime="${datetime##*\n}"

但输出是:

ull)')...
2013:08:22 18:01:16

为什么这不起作用以及如何修复它?

答案1

使用 ANSI C 风格的转义序列$'\n'来指示换行符:

% echo "$datetime"       
ExifMnoteCanon: Loading entry 0xcf27 ('(null)')...
ExifMnoteCanon: Loading entry 0x3ca8 ('(null)')...
ExifMnoteCanon: Loading entry 0xf88a ('(null)')...
2013:08:22 18:01:16

% echo "${datetime##*\n}"
ull)')...
2013:08:22 18:01:16

% echo "${datetime##*$'\n'}"
2013:08:22 18:01:16

正如您所看到的,否则\n将被视为字面意思n

答案2

虽然$''现在非常便携sh(例如,BSD支持 if,尽管其下游分支dash不支持), POSIXLY:

eval 'printf "%s\n" "${datetime##*"'"$(printf '\n"')}\""

...会起作用,即使它很烦人。不过,我通常在变量中保留换行符$nl,所以:

printf "%s\n" "${datetime##*$nl}"

...更易于管理。当然你可以这样做:

printf "%s\n" "${datetime##*"
"}"

……但也许看起来有点滑稽。

答案3

或者,使用最新版本,bash您可以使用mapfile和处理替换将exif输出存储到数组中,然后访问最后一个元素

mapfile -t arr < <(
         exif --debug --machine-readable --tag=DateTimeOriginal "$file" 2>&1)
printf '%s\n' "${arr[@]:(-1)}"
2013:08:22 18:01:16

相关内容