使用 AWK 匹配第一个表达式,如果存在则找到下一个模式,然后插入

Using AWK to match the first expression, if it exists find next pattern, then insert

我有以下文件片段,dbScripts/product.js:

db.ShoppingCart.update(
    { 'identifier': 'COFFEE' },
    {
      'name': 'Coffee',
      'identifier': 'COFFEE',
      'category': 'Beverages',
      'type': [
        {
          'name': 'Rage',
          'identifier': 'COFFEE_RAGE',
          'desc':
            'Coffee by Rage'
        },
        {
            'name': 'Sleepy Owl',
            'identifier': 'COFFEE_SLEEPY_OWL',
            'desc':
              'Coffee by Sleepy Owl'
        }
      ]
    },
    { upsert: true }
); 

我希望先匹配 {'identifier': 'COFFEE'},如果它存在,然后再寻找下一个后续模式 'type': [

如果两个条件都满足,代码应该为其他咖啡品牌插入类似的对象。但是如果输入的标识符不是咖啡,它会为它创建整个结构。 [后半部分已经完成]。

FILE_PATH="./dbScripts/products.js"
# example, COFFEE
echo "Enter product"
read -r PRODUCT_NAME

DESCRIPTION="Coffee by Nescafe"
IDENTIFIER="COFFEE_NESCAFE"

FOUND=$(awk -v ITEM="{ \'identifier\': \'${PRODUCT_NAME}\' }" 'BEGIN {FOUND=0}/ITEM/{++FOUND} END {print FOUND+0}' "${FILE_PATH}")
        echo ${FOUND}
        if [ ${FOUND} -eq 1 ]; then
            SCRIPT_TEMPLATE="./AutomationUtil/object.tpl"
            local SCRIPT=$(eval "echo \"$(cat "${SCRIPT_TEMPLATE}")\"")
            awk -v text="${SCRIPT}" '1;/'type': | 'types': /{printf text}' "${FILE_PATH}" > "${FILE_PATH}_tmp" && mv "${FILE_PATH}_tmp" "${FILE_PATH}"
        fi

我正在尝试使用 awk 变量 FOUND 作为标志来检查是否找到模式。当且仅当 FOUND=1

时才继续下一个模式

Object.tpl

{'name': '${PRODUCT_NAME}','identifier': '${PRODUCT_IDENTIFIER}','desc':'${DESCRIPTION}'},

因此,如果找到两个后续模式,将评估并插入上述模板。否则,来自 dbScripts/product.js 的整个对象结构将在文件末尾创建,例如,用户输入 Tea 而不是 Coffee。

在下面的示例中,用户输入 COFFEE 作为标识符,它与我们的第一个模式 {'identifier': 'COFFEE'} 匹配,然后找到行 'type': [,并且在其下方插入评估的 Object.tpl。

预期输出:

    db.ShoppingCart.update(
            { 'identifier': 'COFFEE' },
            {
              'name': 'Coffee',
              'identifier': 'COFFEE',
              'category': 'Beverages',
              'type': [
                {
                  'name': 'Nescafe',
                  'identifier': 'COFFEE_NESCAFE',
                  'desc':
                    'Coffee by Nesafe'
                },
                {
                  'name': 'Rage',
                  'identifier': 'COFFEE_RAGE',
                  'desc':
                    'Coffee by Rage'
                },
                {
                    'name': 'Sleepy Owl',
                    'identifier': 'COFFEE_SLEEPY_OWL',
                    'desc':
                      'Coffee by Sleepy Owl'
                }
              ]
            },
            { upsert: true }
        );

  db.ShoppingCart.update(
            { 'identifier': 'NOODLES' },
            {
              'name': 'Noodles',
              'identifier': 'NOODLES',
              'category': 'Instant Food',
              'type': [
                {
                  'name': 'Ramen',
                  'identifier': 'NOODELS_RAMEN',
                  'desc':
                    'Noodles by Ramen'
                }
               ]
           }, {upsert: true}
         );

我从理论上想出了这个,但似乎无法实现。我总是得到 FOUND=0.

我敢肯定,此代码非常愚蠢,但我们将不胜感激。同样,应该找到两种模式才能插入对象。

注意:格式由 prettier 处理,因此在插入新文本时应忽略间距

我不想使用 SED,因为 MacOS 没有附带 GNU-SED。

awk version 20200816

当前代码存在一些问题,但由于主要问题似乎是分配给 (bash) 变量的错误值 FOUND,我将只关注这个问题...

主要问题是测试存储在 awk 变量 ITEM 中的搜索模式;一项修复:

/ITEM/    {...}            # wrong
[=10=] ~ ITEM {...}            # fix

将其合并到 OP 的代码中,并为 INPUTFILE_PATH 插入一些值,我们得到:

FOUND=$(awk -v ITEM="{ 'identifier' : '${INPUT}' }" '[=11=] ~ ITEM {++FOUND} END {print FOUND+0}' product.js)
$ echo "${FOUND}"
1

备注:

  • 不需要转义单引号(定义 awk 变量 ITEM
  • awk 变量的初始值为 0,因此不需要 BEGIN{}
  • 此解决方案假设输入具有与 awk 变量 ITEM
  • 中定义的完全相同的白色 space

至于剩下的问题...

  • OP 的第二个 awk 脚本正在寻找字符串 item:items: 但样本输入中不存在这样的字符串,所以我不希望任何东西是 'inserted';目前无法判断这是 typo/issue 与建议的 awk 代码还是错误的样本输入
  • 示例 Object.tpl 文件显示了单行元素定义,但预期的输出显示这是作为多行插入的;这个结果肯定不会由提议的(第二个)awk 脚本生成,因此不确定 OP 是否也在寻找插入换行符或...的 awk 解决方案??
  • 整个 FOUND=$(awk ...); if ... awk ...;fi 代码块可能可以用单个 awk 脚本替换
  • OP 的 awk 版本 (awk version 20200816) 看起来有点奇怪,所以不确定 awk 的 flavor/version 这到底是什么,或者说版本可能有什么限制awk(例如,OP 的 awk 版本是否支持 -i inplace 以允许 awkproduct.js 文件执行 'inplace' 更新?)