我在zsh中编写了一个函数,用一个关键字查找并替换一个特定的数字,稍后我会在一个更大的脚本中使用它。这就是我所拥有的:
function replace_metal() {
for file in "$@"; do
[ -f "$file" ] && mv $file $file.old
# replace metal
awk '/^28\s/ { gsub(/28\s/, "METAL") }; { print }' $file.old > $file
# remove temporary files
rm -f $file.old
done
}
当我在命令行上运行它时,awk部分工作正常但在脚本中,它无法解析文件并用关键字替换数字。我不确定为什么会失败。我写了一个类似于的功能,没有任何问题:
function fix_filename() {
for file in "$@"; do
[ -f "$file" ] && mv $file $file.old
# fix filename
awk '{ gsub(/myFileName/,FILENAME); print }' $file.old > $file.tmp
# clean up filename
awk '{ gsub(/.gjf.old/,""); print }' $file.tmp > $file
# remove temporary files
rm -f $file.old $file.tmp
done
}
我特别感到困惑的是,为什么awk不能在replace_metal函数中工作,而是在命令行上工作。如果有人能够解释,我真的很感激。
这是我运行此脚本的文件的示例部分。它们是我使用的分子几何程序的笛卡尔坐标。
6 4.387152 -0.132561 1.145384
6 4.435130 0.035315 -0.261758
6 3.241800 0.069735 -1.002575
7 2.023205 -0.053248 -0.382329
6 1.948032 -0.217668 0.977856
6 3.120408 -0.260395 1.759133
8 0.936529 -0.001059 -1.144164
28 -0.810634 -0.374713 -0.376819
7 -1.066408 1.593331 -0.221421
6 -2.101594 2.162030 0.386527
6 -3.220999 1.475281 0.925467
7 -2.581803 -0.796964 0.180331
6 -3.412540 0.082878 0.747753
6 -0.299269 -2.264241 -0.449077
1 5.304344 -0.163663 1.737743
1 5.382399 0.136858 -0.794636
1 3.185977 0.187888 -2.085134
1 0.932373 -0.311671 1.366224
1 3.017555 -0.393258 2.837678
1 -2.114644 3.263364 0.463786
1 -4.007715 2.050042 1.415626
1 -4.379471 -0.313239 1.099097
1 -0.572811 -2.828718 0.461055
1 0.789786 -2.379489 -0.603095
1 -0.795666 -2.747919 -1.311858
6 -3.146815 -2.155894 0.046938
1 -2.990568 -2.540510 -0.972499
1 -2.672661 -2.865421 0.746200
1 -4.233217 -2.149944 0.247135
6 -0.086130 2.536630 -0.792152
1 0.886270 2.480474 -0.265799
1 0.102603 2.306402 -1.853394
1 -0.445050 3.580750 -0.720938
第一列中的项目是唯一可以更改的内容。其他三列中的项目不应该改变。
感谢您的帮助!
答案 0 :(得分:3)
问题是“\”字符的转义。试用“\\ s”甚至“\\\\ s”。如果不直接运行脚本,则会对“\” - 字符进行两次评估:首先是shell,然后是awk。无论如何,你的解决方案太复杂了。
尝试:
sed -i "s/^28 /METAL/" file
sed -i表示替换原位,因此您不必将文件“file”复制到“file.old”,然后再将其复制回“file”。
Zsh有一个内置函数来转义字符串:
f="to be escaped"
print ${(q)f}
HTH Chris
答案 1 :(得分:1)
如果你不能赢,引用地狱会让你疯狂(而且你知道有空间而不是标签),只是作弊:
awk '/^28 / { gsub(/^28 /, "METAL ") }; { print }' $file
...或者使用[[:space:]]
代替\s
,看来GNU awk不理解\ s。对我来说,即使是简单的
[0 1047 19:39:10] ~/temp/stack % gawk '/^28\s/ { gsub(/28\s/, "METAL") }; { print }' data
无法替换。 (另外,如果分隔第1列和第2列的唯一内容,请不要更换空间:替换为"METAL "
或仅替换/^28/
。