【问题标题】:Bash grep array as pattern, thinks it's a fileBash grep 数组作为模式,认为它是一个文件
【发布时间】:2020-04-27 13:23:06
【问题描述】:

我正在使用 Heroku cli 从 Heroku 中提取备份列表。我只想抓住那些有计划备份的人 (heroku pg:backups:schedules),但获得他们的 ID 的唯一方法是通过打印所有内容的heroku pg:backups。我正在尝试使用 grep 来减少输出,只给我一个我需要的 ID 列表。

我的想法是,我应该能够使用我需要的备份名称的数组列表,并将其与完整的备份列表进行 grep。但是,grep 要么不喜欢数组的迭代 (array[0]),要么认为我正在传递一个文件名。

for (( x=0; x<DB_COUNT; x++ ))
do
    BACKUP_NAMES[($x)]=$(heroku pg:backups:schedules -a $APP_NAME | sed -n '1!p' | cut -f1 -d":")
    BACKUP_IDS[($x)]=$(heroku pg:backups -a $APP_NAME | grep '[a-z][0-9][0-9][0-9]*' | grep -w $BACKUP_NAMES)
done

我已经尝试过 grep -w ${BACKUP_NAMES[$x]} grep -w "$BACKUP_NAMES[$x]" grep -w "$BACKUP_NAMES" 和其他一千个,但我要么遇到语法错误,要么 grep 认为 $BACKUP_NAMES 是文件而不是模式。几个小时以来我一直试图弄清楚这一点,但我完全被难住了。

编辑:

BACKUP_NAMES 包含DATABASE_NAME DATABASE_NAME2

heroku pg:backups的输出

=== Backups
ID    Created at                Status                              Size     Database
a555 2020-01-09 07:26:21 +0000 Completed 2020-01-09 07:30:08 +0000 1.16GB DATABASE_NAME
a554 2020-01-08 07:26:21 +0000 Completed 2020-01-08 07:30:08 +0000 5.93GB DATABASE_NAME2
a553 2020-01-07 07:26:21 +0000 Completed 2020-01-07 07:30:08 +0000 1.16GB DATABASE_NAME3
a552 2020-01-06 07:26:21 +0000 Completed 2020-01-06 07:30:08 +0000 5.89GB DATABASE_NAME4
a551 2020-01-05 07:26:21 +0000 Completed 2020-01-05 07:30:08 +0000 3.21GB DATABASE_NAME5
a550 2020-01-04 07:26:21 +0000 Completed 2020-01-04 07:30:08 +0000 1.16GB DATABASE_NAME6

heroku pg:backups:schedules的输出

=== Backup Schedules
DATABASE_NAME: daily at 5:00 UTC
DATABASE_NAME2: daily at 7:00 UTC

【问题讨论】:

  • 默认情况下,grep 采用单个正则表达式进行搜索。 BACKUP_NAMES(即heroku pg:backups:schedules 的输出)到底是什么?我认为它类似于由换行符分隔的备份名称列表?名称是否可以包含任何 shell 或正则表达式元字符(空格、星号、问号、方括号……)?
  • 您能否将命令的输出包含在内,这样即使没有安装 heroku,我们也可以尝试一下?
  • 我编辑以回答您的问题。名称从不包含任何元字符。
  • 变量DB_COUNT从何而来?计数器x 在上下文中似乎毫无意义。

标签: bash heroku grep heroku-cli


【解决方案1】:

假设您想将一个数组分配给备份 ID 列表,如何:

for i in $(heroku pg:backups:schedules -a "$APP_NAME" | sed -n '1!p' | cut -f1 -d":"); do
    backup_ids+=($(heroku pg:backups -a "$APP_NAME" | grep -w "$i" | grep -o '[a-z][0-9][0-9][0-9]*'))
done
echo "${backup_ids[@]}"

输出:

a555 a554

[编辑]
如果您的bash 不支持+= 语法,请改用:

for i in $(heroku pg:backups:schedules -a "$APP_NAME" | sed -n '1!p' | cut -f1 -d":"); do
    backup_ids[j]=$(heroku pg:backups -a "$APP_NAME" | grep -w "$i" | grep -o '[a-z][0-9][0-9][0-9]*')
    ((j+=1))
done
echo "${backup_ids[@]}"

【讨论】:

  • 我在第二行遇到问题,似乎认为“+”是 backup_ids 变量名的一部分。如果我在它之间放一个空格,那么它会给我一个“找不到backup_ids命令”的错误。除此之外,这看起来可行!
  • 从 bash-3.1 开始支持 += 赋值运算符(附加到字符串或数组的值)。你能用bash --version找到你的bash版本吗?
【解决方案2】:

您确定需要循环吗?我认为您可以在包括换行符在内的一个变量中捕获备份名称,并将其在进程替换中用作grep -w -f 的参数:

backup_names=$(heroku pg:backups:schedules -a $APP_NAME | sed -n '1!p' | cut -f1 -d":")
heroku pg:backups -a $APP_NAME | grep -w -f <(echo "$backup_names")

我还删除了 grep '[a-z][0-9][0-9][0-9]*',因为它没有更改您提供的数据的输出。

【讨论】:

  • 我希望为备份 ID 列表分配一个数组,正如@tshiono 在他们的回答中所说的那样。它必须与 backup_names 的顺序相同,否则事情会搞砸
  • 当我尝试使用您的代码分配给 backup_ids 时,我只收到“此行错误”BACKUP_NAMES=$(heroku pg:backups:schedules -a $APP_NAME | sed -n '1!p' | cut -f1 -d":") BACKUP_IDS=$(heroku pg:backups -a $APP_NAME | grep -w -f &lt;(echo "$BACKUP_NAMES"))
  • 有两行,不是一行。
猜你喜欢
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 2019-10-28
  • 2015-04-07
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多