我试图在终端中使用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
作为测试,但是它仍然只能在我选择首先列出的文件上运行。为什么会这样?
答案 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)!