使用 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 的代码中,并为 INPUT
和 FILE_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
以允许 awk
对 product.js
文件执行 'inplace' 更新?)
我有以下文件片段,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 的代码中,并为 INPUT
和 FILE_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
以允许awk
对product.js
文件执行 'inplace' 更新?)