我正在使用sed
在运行时更新我的json配置文件。
有时,当模式在json文件中不匹配时,仍会sed
以退货代码0退出。
返回0表示成功完成,但为什么sed
如果找不到正确的模式并更新文件则返回0?是否有解决方法?
谢谢!
答案 0 :(得分:48)
如@cnicutar所述,命令的返回码表示命令是否成功执行。与您在代码/脚本中实现的逻辑无关。
所以如果你有:
echo "foo"|sed '/bar/ s/a/b/'
sed将返回0
但是如果你写了一些语法/表达式错误,或者输入/文件不存在,sed将无法执行你的请求,sed将返回1.
解决方法强>
这实际上不是解决方法。 sed有q
命令:(来自手册页):
q [exit-code]
您可以根据需要定义退出代码。例如,如果'/foo/!{q100}; {s/f/b/}'
不存在,则foo
将以代码100退出,否则执行替换f-> b并使用代码0退出。
匹配案例:
kent$ echo "foo" | sed '/foo/!{q100}; {s/f/b/}'
boo
kent$ echo $?
0
无与伦比的案例:
kent$ echo "trash" | sed '/foo/!{q100}; {s/f/b/}'
trash
kent$ echo $?
100
我希望这能回答你的问题。
修改强>
我必须补充一点,上面的例子只适用于单行处理。我不知道你的具体要求。当你想获得exit 1
时。单行不匹配或整个文件。如果整个文件不匹配,您可以考虑使用awk,甚至在文本处理之前执行grep
...
答案 1 :(得分:47)
这可能适合你(GNU sed):
sed '/search-string/{s//replacement-string/;h};${x;/./{x;q0};x;q1}' file
如果找到search-string
,则会将其替换为replacement-string
,文件结束时sed
将以0
返回代码退出。如果不进行替换,则返回码为1
。
更详细的解释:
用户可以使用两个寄存器:当前行加载到的模式空间(PS)(减去换行符)和一个最初为空的称为保持空间(HS)的备用寄存器。 / p>
一般的想法是使用HS作为标志来指示是否发生了替换。如果HS在文件末尾仍为空,则表示未进行任何更改,否则会发生更改。
命令/search-string/
将search-string
与PS中的任何内容匹配,如果发现它包含search-string
,则执行以下大括号之间的命令。
首先替换s//replacement-string/
(sed使用最后一个正则表达式,即search-string
,如果左侧是空的,那么s//replacement-string
与s/search-string/replacement-string/
相同,并且在此之后,h
命令会复制PS并将其放入HS中。
sed命令$
用于识别文件的最后一行,然后发生以下行。
首先x
命令交换两个寄存器,因此HS成为PS,PS成为HS。
然后在PS中搜索任何字符/./
(.
表示匹配任何字符)记住HS(现在PS)最初是空的,直到替换发生。如果条件为真,则再次执行x
,然后执行q0
命令,该命令结束所有sed处理并将返回代码设置为0
。否则执行x
命令,返回代码设置为1
。
N.B。虽然q
退出sed处理,但它不会阻止PS被sed重新组装并按正常方式打印。
另一种选择:
sed '/search-string/!ba;s//replacement-string/;h;:a;$!b;p;x;/./Q;Q1' file
或:
sed '/search-string/,${s//replacement-string/;b};$q1' file
答案 2 :(得分:20)
这些答案都太复杂了。编写一些使用grep来判断你想要替换的东西是否存在然后使用sed替换它的shell脚本有什么问题?
grep -q $TARGET_STRING $file
if [ $? -eq 0 ]
then
echo "$file contains the old site"
sed -e "s|${TARGET_STRING}|${NEW_STRING}|g" ....
fi
答案 3 :(得分:1)
以下是我们与sed -rn
或sed -r
一起使用的模式。
整个搜索和替换命令(" s /.../.../...")是可选的。如果使用搜索和替换,对于速度并且已经匹配$ matchRe,我们使用尽可能快的$ searchRe值。其中角色不需要重新验证,而{$ len}用于模式的固定长度部分。
找不到的返回值是$ notFoundExit。
/$matchRe/{s/$searchRe/$replacement/$options; Q}; q$notFoundExit
出于以下原因:
改变Q命令的大小会改变行为,具体取决于何时应该退出。涉及将布尔逻辑应用于多线输入的行为需要在解决方案中更复杂。
答案 4 :(得分:1)
我们有上面的答案,但是我花了一些时间才弄清楚正在发生的事情。我正在尝试为像我这样的sed基本用户提供一个简单的解释。
让我们考虑示例:
echo "foo" | sed '/foo/!{q100}; {s/f/b/}'
在这里,我们有两个sed命令。第一个是'/foo/!{q100}'
,此命令实际上检查模式匹配,如果不匹配,则返回存在代码100
。考虑下面的示例,-n
用于使输出静音,因此我们只获得存在的代码。
此示例foo匹配,因此退出代码返回为0
echo "foo" | sed -n '/foo/!{q100}'; echo $?
0
此示例输入为foo
,我们尝试匹配boo
,因此不返回匹配和退出代码100
echo "foo" | sed -n '/boo/!{q100}'; echo $?
100
因此,如果我的要求只是检查模式匹配与否,我可以使用
echo "<input string>" | sed -n '/<pattern to match>/!{q<exit-code>}'
更多示例:
echo "20200206" | sed -n '/[0-9]*/!{q100}' && echo "Matched" || echo "No Match"
Matched
echo "20200206" | sed -n '/[0-9]{2}/!{q100}' && echo "Matched" || echo "No Match"
No Match
第二个命令是'{s/f/b/}'
,它是用我多次使用的f
替换foo
中的b
。
答案 5 :(得分:1)
对于1 行 输入。为了避免重复 /pattern/:
当 s
成功替换时,使用 t
有条件地跳转到一个标签,例如x
。否则使用 q
以退出代码退出,例如100
:
's/pattern/replacement/;tx;q100;:x'
示例:
$ echo 1 > one
$ < one sed 's/1/replaced-it/;tx;q1;:x'
replaced-it
$ echo $?
0
$ < one sed 's/999/replaced-it/;tx;q100;:x'
1
$ echo $?
100
https://www.gnu.org/software/sed/manual/html_node/Branching-and-flow-control.html
答案 6 :(得分:0)
我想在找到匹配项时通过退出截断文件(并排除匹配的行)。当重新运行在文件末尾添加行的进程时,这很方便。 &#34; Q; Q1&#34;没有工作,只是&#34; Q1&#34;做了,如下:
如果sed -i&#39; / text我想找/ Q1&#39; file.txt的 然后 在文件末尾插入空行+新行 科幻 只插入没有空白行的新行
答案 7 :(得分:0)
正如我们已经知道的那样,当sed无法匹配时,它只返回其输入字符串 - 没有发生错误。确实,输入和输出字符串之间的差异意味着匹配,但匹配并不意味着字符串的差异;毕竟sed可以简单地匹配所有输入字符。 该缺陷在以下示例中创建
g=Xabc1
其中g=abc1
给出1,而设置h=$(echo "fix${g}ed" | sed 's/.*\(abc[[:digit:]]\).*/\1/g')
if [ ! "$h" = "fix${g}ed" ]; then
echo "1"
else
echo "2"
fi
给出2;然而这两个输入字符串都是由sed匹配的!因此,很难确定sed是否匹配。解决方案:
# Input: date in "dd.mm.yyyy hh:mm:ss" format;
# returns true iff the date is more than (24 * days) hours
# in the past relative to `now`
def older(days):
(now - (strptime("%d.%m.%Y %T") | mktime)) # seconds
> (days*24*3600);
在这种情况下,只有当sed匹配时才会打印1。
答案 8 :(得分:0)
对于任意数量的输入行:
sed --quiet 's/hello/HELLO/;t1;b2;:1;h;:2;p;${g;s/..*//;tok;q1;:ok}'
在匹配时填充保留空间,并在最后一行之后检查它。
如果文件中没有匹配项,则返回状态 1
。
s/hello/HELLO
- 替代检查t1
- 如果替换成功,则跳转到标签 1
b2
- 无条件跳转到标签 2
:1
- 标签 1
h
- 复制模式以保留空间(替换成功时):2
- 标签 2
p
- 无条件打印模式空间${ ... }
- 匹配最后一行,评估内部块g
- 将保持空间复制到模式空间(如果第一次替换之前成功则非空)s/..*//
- 虚拟替换,设置分支标志tok
- 跳转到标签 ok
(如果虚拟替换在非空保持空间上成功)q1
- 以错误状态 1 退出:ok
- 标签 ok