【问题标题】:redirecting in a shell script在 shell 脚本中重定向
【发布时间】:2013-12-21 15:47:37
【问题描述】:

我正在尝试编写一个脚本来交换文件中的文本:

sed s/foo/bar/g myFile.txt > myFile.txt.updated
mv myFile.txt.updated myFile.txt

我调用了 sed 程序,该程序交换了 myFile.txt 中的文本并将更改的文本行重定向到第二个文件。 mv 然后将 .updated txt 文件移动到 myFile.txt,覆盖它。该命令在 shell 中有效。

我写道:

#!/bin/sh
#First, I set up some descriptive variables for the arguments
initialString="$1"
shift
desiredChange="$1"
shift
document="$1"
#Then, I evoke sed on these (more readable) parameters
updatedDocument=`sed s/$initialString/$desiredChange/g $document`
#I want to make sure that was done properly
echo updated document is $updatedDocument
#then I move the output in to the new text document
mv $updatedDocument $document

我得到错误:

mv: 目标 `myFile.txt' 不是目录

我知道它认为我的新文件名是 sed 输出的字符串的第一个单词。我不知道如何纠正。从早上 7 点开始,我一直在尝试每条报价单,创建一个临时文件来将输出存储在(灾难性的结果)、IFS 中……到目前为止,一切都给了我越来越多的无用错误。我需要清醒一下,我需要你的帮助。我该如何解决这个问题?

【问题讨论】:

  • 您似乎正在尝试运行您使用某些通配符模式作为输入文件编写的脚本。尝试使用一个文件作为文件名运行,看看会发生什么。
  • 我敢打赌,当你双引号 all 你的变量时你会没事的。如果您发布了脚本的所有输入/参数和输出,将会很有用。
  • @user2719058,呃,不,你不好。

标签: unix replace sed sh


【解决方案1】:

不妨试试

echo $updatedDocument > $document

【讨论】:

  • 而不是echo,我相信你的意思是cat。正确的 ?实际上最好使用cat $updatedDocument > $document 构造,因为这样可以保持文件的所有权和权限不变,前提是您对该文件具有读/写访问权限。
  • 不,sed 命令的输出现在在变量 updatedDocument 中。 updatedDocument 包含文件的内容,而不是文件名。
  • 大声笑多么时尚的解决方案!即使使用反引号,它也能像魅力一样工作,当然因为它将字符串存储在变量中,但随后 echo 的输出变成了字符串,并且由于它只是“程序的输出”,重定向运算符适用于 .txt 文件。
【解决方案2】:

改变

updatedDocument=`sed s/$initialString/$desiredChange/g $document`

updatedDocument=${document}.txt
sed s/$initialString/$desiredChange/g $document

反引号实际上会将 sed 命令的整个管道输出放入您的变量值中。

一种更快的方法是完全不使用updatedDocumentmv,而是直接使用sed

sed -i s/$initialString/$desiredChange/g $document

-i 标志告诉 sed 就地进行替换。这基本上意味着为输出创建一个临时文件,并在完成后用临时文件替换您的原始文件,几乎与您正在做的一样。

【讨论】:

  • 等一下,我正在修改它,非常感谢! (这台服务器上的 emacs 有点慢)
  • 天哪,这太有帮助了。以快速的方式进行操作!我收到“冗余”错误?这样做很长,就像:正如你所拥有的那样:mv cannot stat `myFile.txt.txt':没有这样的文件或目录。删除尾随 .txt 后: mv: myFile.txt 和 myFile.txt 是同一个文件。今晚我会学习,尝试一些东西并弄清楚它是如何搞砸的。这就是这样做的乐趣所在,感谢你,我得到了这份特权:)
  • 如果您喜欢我的解决方案,可以点赞或选择它作为答案。
【解决方案3】:
#!/bin/sh
#First, I set up some descriptive variables for the arguments
echo "$1" | sed #translation of special regex char like . * \ / ? | read -r initialString
echo "$2" | sed 's|[\&/]|\\&|g' | read -r desiredChange
document="$3"

#Then, I evoke sed 
sed "s/${initialString}/${desiredChange}/g" ${document} | tee ${document}

不要忘记 initialString 和 desiredChange 被模式解释为正则表达式,所以肯定需要翻译 sed #translation of special regex char like . * \ / ? 是替换为正确的sed(在网站上的几个帖子讨论)

【讨论】:

  • 谢谢,你说的很对。我希望你已经链接到其中的一些讨论,我整天都在尝试搜索它们,这个网站很大,总共使用了大约 50 个关键字! (尝试像输入 sed unix 等搜索。你永远不会得到你想要的结果)
猜你喜欢
  • 2018-01-20
  • 1970-01-01
  • 2023-03-04
  • 2010-09-05
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-23
相关资源
最近更新 更多