我绝不是AppleScript专家,而是过得去。我正试图将一些AppleScript变量传递给sed
命令,以便根据变量替换文件中的某些文本。
我在AppleScript中有两个抓取用户数据的对话框,我存储这些变量。 myData
- 这很好用。
set myData to text returned of ¬
(display dialog "Enter Your Data" with title ¬
"Data Entry" default answer ¬
"" buttons {"Continue…"} ¬
default button 1 ¬
)
set searchFor to quoted form of "data1"
set searchFor2 to quoted form of "data2"
set inputFile to "/Users/User1/Desktop/file.txt"
set outputFile to "/Users/User1/Desktop/file1.txt"
do shell script quoted form of ("sed -i.bak s/" & searchFor & "/" & myData & "/g") & " " & inputFile & " > " & outputFile
我实际收到此错误:No such file or directory
,退出代码127
。但奇怪的是,它确实写出了包含零数据的文件。我不一定像脚本建议写出一个diff文件,只是编辑数据。但是,我没有那样成功,这就是我这样做的原因。
对我的问题的任何帮助将不胜感激!
答案 0 :(得分:4)
您的即时问题是您错误地应用了quoted form of
多次次,而且更重要的是将quoted form of
应用于sed
可执行文件名称及其选项以及sed
脚本一起,这些文件总是会中断(有关详细说明,请参见下文) );尝试以下操作 - 不事先将quoted form of
应用于任何变量 - 请注意选择性如何应用quoted form of
sed
脚本以及输入和输出文件:
do shell script "sed " & quoted form of ¬
("s/" & searchFor & "/" & myData & "/g") ¬
& " " & quoted form of inputFile & " > " & quoted form of outputFile
请注意,我已从命令中删除-i.bak
,因为它总是会导致空输出文件:-i
更新输入文件到位,生成 no stdout output 。因此, nothing 将通过outputFile
发送给> outputFile
。
但是,如果searchFor
和myData
包含/
或sed
正则表达式中具有特殊含义的字符,则此仍然可能会中断或行为异常< / strong>(例如,\
,*
,[
,...)或替换字符串(例如&
,{{1 }})。
为了避免这种情况,你必须首先转义输入字符串,不幸的是,这非常重要。
以下处理程序 提供强大的通用转义 - 它们基于this answer,其中解释了基础命令 [1] ):
\
[1]需要进行一些调整才能使它们与# Quotes (escapes) a string for safe use in a `sed` regex.
on quoteRegex(txt)
do shell script "sed -e 's/[^^]/[&]/g; s/\\^/\\\\^/g; $!a\\'$'\\n''\\\\n' <<<" & quoted form of txt & " | tr -d '\\n'"
end quoteRegex
# Quotes (escapes) a string for safe use in a `sed` substitution string (`s///` function).
on quoteSubst(txt)
do shell script "IFS= read -d '' -r <<<\"$(sed -e ':a' -e '$!{N;ba' -e '}' -e 's/[&/\\]/\\\\&/g; s/\\n/\\\\&/g' <<<" & quoted form of txt & "; printf X)\"; printf %s \"${REPLY%$'\\n'X$'\\n'}\"" without altering line endings
end quoteSubst
一起使用;值得注意的是,不支持流程替换(do shell script
);通过<(...)
的变通方法需要额外的步骤来准确地保留输入中的尾随换行符。
将上面的处理程序粘贴到您的脚本后,以下是如何将它们应用于您的命令:
<<<"$(...)"
至于你原始症状:
但奇怪的是,它确实写出了包含零数据的文件。
这表明do shell script "sed " & quoted form of ¬
("s/" & my quoteRegex(searchFor) & "/" & my quoteSubst(myData) & "/g") ¬
& " " & quoted form of inputFile & " > " & quoted form of outputFile
(a)能够调用shell,(b)shell解析命令行而不会遇到语法错误;如果满足这些条件,则输出重定向(例如do shell script
)会将目标文件创建作为零字节文件,或者,如果存在,则将其截断为零字节文件,BEFORE命令执行开始。
如果命令执行失败,则会遗留零字节文件。
我实际上得到了这个错误:没有这样的文件或目录,退出代码127
退出代码> outFile
表示无法调用作为命令字符串第一个标记的可执行文件,因为无法找到它。
确实发生了这种情况,因为您错误地将127
应用于quoted form of
可执行文件名称,其选项以及sed
脚本一起,这会导致将整个结果字符串解释为可执行文件名,这显然会失败。
我们举一个简化的例子:
sed
产生quoted form of "sed s/foo/bar/g file"
,包括封闭的单引号。
将此字符串传递给shell会导致shell将此字符串视为构成可执行文件路径或文件名的单个标记。显然,没有名为'sed s/foo/bar/g file'
的文件,因此命令失败。
如上所示,解决方案是将sed s/foo/bar/g file
,其选项,脚本以及输入文件名和输出文件名作为单独的标记传递。