使用 grep 和 sed 查找和替换字符串

发布于 2024-11-10 15:38:34 字数 342 浏览 1 评论 0原文

我使用以下命令递归地搜索目录中的特定字符串并将其替换为另一个字符串:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g'

这可以正常工作。唯一的问题是,如果字符串不存在,则 sed 会失败,因为它没有获取任何参数。这对我来说是一个问题,因为我使用 ANT 自动运行它,并且由于 sed 失败而构建失败。

有没有办法在找不到字符串的情况下防止失败?

我对可以使用的一行简单解决方案感兴趣(不一定使用 grepsed 但使用像这样的常见 UNIX 命令)。

I am using the following to search a directory recursively for specific string and replace it with another:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g'

This works okay. The only problem is that if the string doesn't exist then sed fails because it doesn't get any arguments. This is a problem for me since i'm running this automatically with ANT and the build fails since sed fails.

Is there a way to make it fail-proof in case the string is not found?

I'm interested in a one line simple solution I can use (not necessarily with grep or sed but with common unix commands like these).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

久夏青 2024-11-17 15:38:35

我采纳了弗拉德的想法并做了一些改变。 而不是在其中

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null

进行生成,

sed: couldn't edit /dev/null: not a regular file

我正在与远程服务器建立 3 个不同的连接,

touch deleteme
grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' ./deleteme
rm deleteme

尽管这不太优雅并且需要与服务器的另外 2 个连接(也许有一种方法可以在一行中完成所有操作),但它也可以高效地完成工作

I have taken Vlad's idea and changed it a little bit. Instead of

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null

Which yields

sed: couldn't edit /dev/null: not a regular file

I'm doing in 3 different connections to the remote server

touch deleteme
grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' ./deleteme
rm deleteme

Although this is less elegant and requires 2 more connections to the server (maybe there's a way to do it all in one line) it does the job efficiently as well

似最初 2024-11-17 15:38:35

标准的 xargs 没有好的方法来做到这一点;您最好按照其他人的建议使用 find -exec ,或者将 sed 包装在一个脚本中,如果没有参数,该脚本将不执行任何操作。 GNU xargs 具有 --no-run-if-empty 选项,BSD / OS X xargs 具有 -L< /code> 选项看起来应该做类似的事情。

Standard xargs has no good way to do it; you're better off using find -exec as someone else suggested, or wrap the sed in a script which does nothing if there are no arguments. GNU xargs has the --no-run-if-empty option, and BSD / OS X xargs has the -L option which looks like it should do something similar.

眼眸印温柔 2024-11-17 15:38:35

我认为,在不使用 -exec 的情况下,您可以简单地提供 /dev/null 作为至少一个参数,以防找不到任何内容:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null

I think that without using -exec you can simply provide /dev/null as at least one argument in case nothing is found:

grep -rl oldstr path | xargs sed -i 's/oldstr/newstr/g' /dev/null
泛泛之交 2024-11-17 15:38:35

我的用例是我想更换
foo:/Drive_Letterfoo:/bar/baz/xyz
就我而言,我可以使用以下代码来完成此操作。
我位于有大量文件的同一目录位置。

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

希望有帮助。

My use case was I wanted to replace
foo:/Drive_Letter with foo:/bar/baz/xyz
In my case I was able to do it with the following code.
I was in the same directory location where there were bulk of files.

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

hope that helped.

野却迷人 2024-11-17 15:38:35

不确定这是否有帮助,但您可以将其与远程服务器一起使用,如下例所示

ssh example.server.com "find /DIR_NAME -type f -name "FILES_LOOKING_FOR" -exec sed -i 's/LOOKINGFOR/withThisString/ g'{};"

将 example.server.com 替换为您的服务器
将 DIR_NAME 替换为您的目录/文件位置
将 FILES_LOOKING_FOR 替换为您要查找的文件
将 LOOKINGFOR 替换为您要查找的内容
将 withThisString 替换为您想要在文件中替换的内容

Not sure if this will be helpful but you can use this with a remote server like the example below

ssh example.server.com "find /DIR_NAME -type f -name "FILES_LOOKING_FOR" -exec sed -i 's/LOOKINGFOR/withThisString/g' {} ;"

replace the example.server.com with your server
replace DIR_NAME with your directory/file locations
replace FILES_LOOKING_FOR with files you are looking for
replace LOOKINGFOR with what you are looking for
replace withThisString with what your want to be replaced in the file

罪歌 2024-11-17 15:38:35

如果要替换固定字符串或某些模式,我还想添加 bash 内置模式字符串替换变量替换构造。我没有自己描述它,而是引用 bash 手册中的部分:

${参数/模式/字符串}

该模式被扩展以产生与路径名中一样的模式
扩张。 参数被扩展,模式与其值的最长匹配被字符串替换。如果模式
/ 开头,所有匹配的 pattern 都将替换为字符串。
通常只替换第一个匹配项。如果模式开始
对于 #,它必须匹配扩展值的开头
参数。如果模式%开头,则它必须在末尾匹配
参数的扩展值。如果字符串为空,则匹配
pattern 被删除,pattern 后面的 / 可以省略。如果参数@*,则替换操作为
依次应用于每个位置参数,并且展开
是结果列表。如果参数是下标为@*的数组变量,则替换操作应用于
依次对数组中的每个成员进行扩展,
结果列表。

If you are to replace a fixed string or some pattern, I would also like to add the bash builtin pattern string replacement variable substitution construct. Instead of describing it myself, I am quoting the section from the bash manual:

${parameter/pattern/string}

The pattern is expanded to produce a pattern just as in pathname
expansion. parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern
begins with /, all matches of pattern are replaced with string.
Normally only the first match is replaced. If pattern begins
with #, it must match at the beginning of the expanded value of
parameter. If pattern begins with %, it must match at the end
of the expanded value of parameter. If string is null, matches
of pattern are deleted and the / following pattern may be omitted. If parameter is @ or *, the substitution operation is
applied to each positional parameter in turn, and the expansion
is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to
each member of the array in turn, and the expansion is the
resultant list.

沫离伤花 2024-11-17 15:38:34

您可以直接在 sed 中使用 find-exec,而不是先使用 grep 定位 oldstr代码>.它的效率可能会低一些,但这可能并不重要。这样,sed 替换就会在 find 列出的所有文件上执行,但如果 oldstr 不存在,它显然不会对其进行操作它。

find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \;

You can use find and -exec directly into sed rather than first locating oldstr with grep. It's maybe a bit less efficient, but that might not be important. This way, the sed replacement is executed over all files listed by find, but if oldstr isn't there it obviously won't operate on it.

find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \;
冷血 2024-11-17 15:38:34

你的解决方案没问题。仅以这种方式尝试:

files=$(grep -rl oldstr path) && echo $files | xargs sed....

因此仅当 grep 返回 0 时才执行 xargs,例如在某些文件中找到该字符串时。

Your solution is ok. only try it in this way:

files=$(grep -rl oldstr path) && echo $files | xargs sed....

so execute the xargs only when grep return 0, e.g. when found the string in some files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文