sed命令中的通配符替换字符串不起作用

时间:2019-05-10 20:20:28

标签: string bash macos sed replace

我试图在终端中使用sed命令,用特定的字符串替换具有特定扩展名的所有文本文件中的特定行:

sed -i.bak '35s/^.*$/5\) 1\-4/' fitting_file*.feedme

因此,我尝试将每个文件中的第35行替换为字符串“ 5)1-4”。在此目录中运行ls fitting_file*.feedme | wc -l命令时,我得到221个文件。但是,当我运行上述sed命令时,它仅按ls fitting_file*.feedme的顺序编辑FIRST文件。我知道这是因为grep '5) 1-4' fitting_file*.feedme仅在我运行替换命令后才连续返回列表中的第一个文件。我还尝试在fitting_file*.feedme命令中用空格分隔的两个文件列表代替sed作为测试,但是它仍然只能在我选择首先列出的文件上运行。为什么会这样?

3 个答案:

答案 0 :(得分:0)

sed单个流上运行。它实质上将所有文件合并在一起,并将其视为单个流。因此,它取代了大串联流的第35行。

要查看此信息,请制作一个名为A的20行文件和一个名为B的20行文件。将sed命令应用为

sed -i.bak '35s/^.*$/5\) 1\-4/' A B

您将看到B的第15行被替换。

我认为这应该回答您的直接问题。至于如何完成您喜欢的事情,我想您已经知道将sed命令包装在for中是做到这一点的一种方法。 :)

答案 1 :(得分:0)

尝试

创建一个包含sed指令的文件

    if let imgData = img.jpegData(compressionQuality: 0.2) {

        let imgUid = NSUUID().uuidString

        let metadata = StorageMetadata()

        metadata.contentType = "image/jpeg"

        Storage.storage().reference().child(imgUid).putData(imgData, metadata: metadata) { (metadata, error) in

            if error != nil {
                print ("Did not upload image")

            } else {

                print("uploaded")

                let downloadURL = metadata?.downloadURL()?.absoluteString

                if let url = downloadURL {

                    self.setUser(img: url)
                }
            }
        }

    }

并将其称为prog.sh。接下来使其可执行:

#!/bin/bash 
sed -i.bak '35s/^.*$/5\) 1\-4/' $1
exit 0

现在您可以使用来解决问题

chmod u+x prog.sh

您可以在一行上完成所有这些操作,但是坦率地说,所需的转义次数会很多。祝你好运。

答案 2 :(得分:0)

不使用shell loop即可执行的操作是:

awk -i inplace -v inplace::suffix=.bak 'FNR==35{$0="5) 1-4"}1' fitting_file*.feedme

请注意,与sed只能对所有输入文件中的行进行计数不同,awk具有NR来跟踪所有文件中的记录数(默认情况下为行),而FNR则用于跟踪相同文件但仅在内部当前文件。

上面的代码使用GNU awk进行就地编辑,就像GNU sed为此-i。 MacOS上的默认awk是BSD awk,而不是GNU awk,但是您应该安装GNU awk,因为它没有BSD awk的所有错误/怪癖,并且具有大量非常有用的扩展。

如果您只想使用MacOS的awk,则可能是这样的:

find . -name 'fitting_file*.feedme' -exec sh -c "\
    awk 'FNR==35{\$0=\"5) 1-4\"}1' \"\$1\" > \"\$1.bak\" &&
    mv -- \"\$1.bak\" \"\$1\"
" sh {} \;

这显然变得有点复杂-我可能会将awk + ​​mv脚本放在一个文件中,以从sh -c执行,或者如果遇到这种选择(或类似的引用梦night),则自己诉诸shell循环与xargs)!

相关问题