Bash Scripting:如果行以(或匹配)另一个字符串开头,则替换(或删除)文件中的字符串

时间:2011-02-19 08:07:57

标签: linux bash string

假设像这样的ini风格的文件,

[Group]
Icon=xxx.ico
Title=An Image Editor
Description=Manipulates .ico, .png and .jpeg images

我想在以(或匹配)“Icon =”

开头的行中替换/删除“.ico”

我正在尝试这个:

oldline="`cat "$file" | grep "Icon="`"
newline="`echo "$oldline" | tr ".ico" ".png"`"
cat "$oldfile" | tr "$oldline" "$newline" > $file

然后我意识到tr的作用与我想的完全不同。它不是一个传统的“替换为此”功能。所以我想正确的方法是使用sed。但是:

  • 之前从未使用过sed。不知道它是如何工作的。是否有点过分?
  • 如果最明确的方式是真正使用sed,鉴于它是如此强大,有没有任何优雅的方法来实现这一点,而不是这个“获取行 - >修改行 - >替换oldline for newline in文件“方法?

注意:

  • 我不能全局替换“.ico”,我知道这将更容易,我必须将替换限制为Icon行,否则Description行也会被更改。
  • 我不熟悉Linux中的shell脚本,所以我不仅要寻找解决方案本身,还要寻找“正确”的方法。优雅,易读,传统等

提前致谢!

修改

谢谢你们!这是最终的脚本,作为参考:

#! /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

比我原来的更光滑!我唯一遗憾的是sed备份不保留原始文件时间戳。但我可以忍受这一点。

而且,为了记录,是的,我已经创建了这个脚本来修复Skype包装中的实际“错误”。

2 个答案:

答案 0 :(得分:6)

像sed中的以下内容应该做你需要的。首先,我们检查该行是否以Icon=开头,如果是,则运行s命令(即替换)。

sed -i '/^Icon=/s/\.ico$/.png/' file

编辑:上面的sed脚本也可以这样写:

/^Icon=/ {             # Only run the following block when this matches
    s/\.ico$/.png/     # Substitute '.ico' at the end of the line with '.png'
}

有关如何限制命令运行时间的详细信息,请参阅this page

答案 1 :(得分:3)

sed非常容易处理。这是一种方式:

sed 's/^\(Icon=.*\)\.ico$/\1.png/'

默认情况下,sed一次只能处理文件中的每一行。 's /.../.../'将在第一个参数上进行正则表达式匹配,并将其替换为第二个参数。 \ 1表示与第一组匹配的所有内容,由括号划分。你必须用\。

逃脱

以上工作作为管道的一部分,但您可以添加'-i'标志,如此

sed -i 's/^\(Icon=.*\)\.ico$/\1.png/' input.txt

让它替换文件input.txt到位。在稍微测试一下sed脚本之前,请不要添加它。