Linux Bash 脚本:如果行以(或匹配)另一个字符串开头,则替换(或删除)文件中的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5049652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash Scripting: Replace (or delete) string in a file if line starts with (or matches) another string
提问by MestreLion
Assuming an ini-style file like this,
假设一个像这样的 ini 风格的文件,
[Group]
Icon=xxx.ico
Title=An Image Editor
Description=Manipulates .ico, .png and .jpeg images
I want to replace/delete ".ico" ONLY in the line that starts with (or matches) "Icon="
我只想在以(或匹配)“Icon=”开头的行中替换/删除“.ico”
I was trying this:
我正在尝试这个:
oldline="`cat "$file" | grep "Icon="`"
newline="`echo "$oldline" | tr ".ico" ".png"`"
cat "$oldfile" | tr "$oldline" "$newline" > $file
Then i realized that tr
works completely different than i thought. Its NOT a tradicional "replace this for that" function. So i guess the correct way is using sed
. But:
然后我意识到这tr
与我想象的完全不同。它不是传统的“用这个代替那个”功能。所以我猜正确的方法是使用sed
. 但:
- Ive never used
sed
before. No idea how it works. Is it overkill? - If the most indicated way is really using
sed
, given it is so powerful, is there any elegant way to accomplish this rather than this "fetch line -> modify line -> replace oldline for newline in file" approach?
- 我以前从未使用
sed
过。不知道它是如何工作的。是否矫枉过正? - 如果最指示的方式是真正使用
sed
,鉴于它如此强大,有没有什么优雅的方法来完成这个而不是这种“获取行 - >修改行 - >替换文件中的换行符的旧行”方法?
Notes:
笔记:
- I cant replace ".ico" globally, i know that would be a LOT easier, i must restrict the replace to the Icon line, otherwise the Description line would be changed too.
- Im new to shell scripting in Linux, so im looking not only to the solution itself, but also for the "proper" way to do it. Elegant, easy to read, conventional, etc
- 我不能全局替换“.ico”,我知道这会容易很多,我必须将替换限制在图标行,否则描述行也会被更改。
- 我是 Linux 中 shell 脚本的新手,所以我不仅要寻找解决方案本身,还要寻找“正确”的方法来做到这一点。优雅、易读、常规等
Thanks in advance!
提前致谢!
Edit:
编辑:
Thank you guys! Here is the final script, as a reference:
谢谢你们!这是最终的脚本,作为参考:
#! /bin/bash
# Fix the following WARNING in ~/.xsession-errors
# gnome-session[2035]: EggSMClient-WARNING: Desktop file '/home/xxx/.config/autostart/skype.desktop' has malformed Icon key 'skype.png'(should not include extension)
file="$HOME/.config/autostart/skype.desktop"
if [ -f "$file" ] ; then
if `cat "$file" | grep "Icon=" | grep -q ".png"` ; then
sed -i.bak '/^Icon=/s/\.png$//' "$file"
cp "$file" "$PWD"
cp "${file}.bak" "$PWD"
else
echo "Nothing to fix! (maybe fixed already?)"
fi
else
echo "Skype not installed (yet...)"
fi
MUCH sleeker than my original! The only thing i regret is that sed
backup does not preserve original file timestamp. But i can live with that.
比我原来的更时尚!我唯一遗憾的是sed
备份不保留原始文件时间戳。但我可以忍受。
And, for the record, yes, ive created this script to fix an actual "bug" in Skype packaging.
而且,作为记录,是的,我创建了这个脚本来修复 Skype 打包中的一个实际“错误”。
采纳答案by a'r
Something like the following in sed should do what you need. First we check if the line starts with Icon=
and if it does then we run the s
command (i.e. substitute).
sed 中的以下内容应该可以满足您的需求。首先,我们检查该行是否以 开头,Icon=
如果是,则运行s
命令(即替换)。
sed -i '/^Icon=/s/\.ico$/.png/' file
Edit:The sed script above can also be written like this:
编辑:上面的 sed 脚本也可以这样写:
/^Icon=/ { # Only run the following block when this matches
s/\.ico$/.png/ # Substitute '.ico' at the end of the line with '.png'
}
See this pagefor more details on how to restrict when commands are run.
有关如何限制运行命令的更多详细信息,请参阅此页面。
回答by Steven Ourada
sed is pretty easy to deal with. Here's one way:
sed 很容易处理。这是一种方法:
sed 's/^\(Icon=.*\)\.ico$/.png/'
By default, sed works on every line in the file one at a time. The 's/.../.../' will do a regular expression match on the first argument and replace it with the second argument. The \1 stands for everything that matched the first group, which is demarcated by the parenthesis. You have to escape the parens with \.
默认情况下, sed 一次处理文件中的每一行。's/.../.../' 将对第一个参数进行正则表达式匹配并将其替换为第二个参数。\1 代表与第一组匹配的所有内容,由括号划定。你必须用 \ 来逃避括号。
The above works as part of a pipeline, but you can add an '-i' flag, like this
以上作为管道的一部分工作,但您可以添加一个“-i”标志,如下所示
sed -i 's/^\(Icon=.*\)\.ico$/.png/' input.txt
to have it replace the file input.txt in place. Don't add that until you have tested your sed script a little.
让它替换文件 input.txt 到位。在您稍微测试了 sed 脚本之前不要添加它。