我在替换bash字符串中的变量时遇到问题。例如,我要替换
$resulting = $query->result_array();
$currentDateTime = date('Y-m-d H:i:s');
foreach($resulting as $resultings){
$date = $resultings['eventDate'];
$this->db->where('activityId', $resultings['activityId']);
if (strtotime($currentDateTime) == strtotime($date)) {
$this->db->update('activity', array('eventStatus' => 1));
} else if (strtotime($currentDateTime) < strtotime($date)) {
$this->db->update('activity', array('eventStatus' => 3));
} else if (strtotime($currentDateTime) > strtotime($date)) {
$this->db->update('activity', array('eventStatus' => 1));
}
}
具有:
"test$FOO1=$FOO2" $BAR
我尝试过:
"test" .. FOO1 .. "=" .. FOO2 .. "" $BAR
但是我不想用双引号之外的字符串来替换变量,例如喜欢:
sed 's/\$\([A-Z0-9_]\+\)\b/" .. \1 .. "/g'
只需替换为
if [ $VARIABLE = 1 ]; then
是否可以仅替换内部双引号?
背景:
我要convert a bash script into Lua script。
我知道,以这种方式转换所有可能的shell脚本不是一件容易的事,但是我要实现的是用Lua命令替换所有基本语言结构,并替换所有变量和条件。将bash手动翻译成Lua时,这里的自动化将节省大量工作
答案 0 :(得分:0)
这与用于多字符RS,RT和gensub()的GNU awk一起,展示了一种分离并随后处理带引号(在RT中)和无引号(在$ 0中)字符串作为起点的方法:
$ cat tst.awk
BEGIN { RS="\"[^\"]*\""; ORS="" }
{
$0 = gensub(/\[\s+[$]([[:alnum:]_]+)\s+=\s+\S+\s+];/,"\\1","g",$0)
RT = gensub(/[$]([[:alnum:]_]+)"/,"\" .. \\1","g",RT)
RT = gensub(/[$]([[:alnum:]_]+)/,"\" .. \\1 .. \"","g",RT)
print $0 RT
}
$ awk -f tst.awk file
"count: " .. FOO .. " times " .. BAR
if VARIABLE then
以上操作是在此输入文件上执行的:
$ cat file
"count: $FOO times $BAR"
if [ $VARIABLE = 1 ]; then
注意:根据提供的示例,这种将字符串与正则表达式匹配的方法永远只是尽力而为,您需要一个shell语言解析器来稳健地完成这项工作。
答案 1 :(得分:0)
这可能对您有用(GNU sed):
sed -E ':a;s/^([^"]*("[^"$]*"[^"]*)*"[^"$]*)\$([^" ]*) /\1" .. \3 .. " /;ta;s/^([^"]*("[^"$]*"[^"]*)*"[^"$]*)\$([^"]*)"/\1" .. \3/;ta' file
在双引号中更改内容时,首先,我们必须通过任何不需要需要更改的双引号字符串。这意味着使用^
元字符将正则表达式锚定到行的开头,并迭代正则表达式直到所有情况都不再存在。
首先,请从行首开始消除零个或多个不是双引号的字符。
第二,消除不包含感兴趣字符(TCOI)的双引号字符串,即$
,后跟零个或多个不是双引号的字符,零次或多次。
第三,消除双引号,后跟零个或多个不是双引号或TCOI的字符,即$
。
以下字符(如果存在)必须为TCOI。在反向引用\1
之前将整个字符串集合分组。
在TCOI之后,可以对一个或多个条件进行分组。在上面的示例中,第一个条件是变量(以TCOI开头)后跟空格。第二个条件是变量直接跟在"
之后。因此,这需要两个替换命令ta
命令,当替换成功时,它们会分支到标识为a
的循环。
if [ $VARIABLE = 1 ]; then
的情况可以用同样的方式处理,这里的[
是开始的双引号,]
是结束的双引号。
P.S。 TCOI为$
,它也是regexp中的一个元字符,代表一行的结尾,因此必须用例如\$
P.P.S。不要忘记引用[
和]
。如果引用不是您的事,则将字符括在[x]
中,其中x是要引用的字符。
编辑:
sed -E ':a;s/^([^"]*("[^"$]*"[^"]*)*"[^"$]*)\$([[:alnum:]]*)/\1" .. \3 .. "/;ta' file
由于原始示例已被OP取代,因此以下是基于新示例的解决方案。
答案 2 :(得分:0)
很抱歉:我只是发布此答案以警告您错误的方法!
阅读语言是一致的 lexer 的工作,而不是 sed 或任何基于 regex 的工具! !
请参见GNU Bison,Berkeley Yacc (byacc)。
您可以查看bash的来源,以了解如何阅读脚本!
以这种方式坚持下去将使您快速进入大型脚本,然后进一步解决无法解决的问题。
答案 3 :(得分:0)
使用组和递归
sed -e ':a' -e 's/^\(\([^"]*\("[^"]*"\)*\)*\)\("[^$"]*\)[$]\([A-Z0-9_]\{1,\}\)/\1\4 .. \5 .. /;t a'
^\(\([^"]*\("[^"]*"\)*\)*\)
s\("[^$"]*\)[$]\([A-Z0-9_]\{1,\}\)'
分隔的字符串中选择var内容\1\4 .. \5 ..
随心所欲地更改:a
和t a
发生更改时重复此操作使用gnu sed可以将命令减少为(无需使用-e
来定位标签a):
sed ':a;s/^\(\([^"]*\("[^"]*"\)*\)*\)\("[^$"]*\)[$]\([A-Z0-9_]\{1,\}\)/\1\4 .. \5 .. /;t a'
假定字符串中没有引号(转义的一个)。如果是这样,则需要先通过更改它们,然后在进行主要修改后放回它们。