найти и заменить скрипт (сложная проблема ... НУЖНА ПОМОЩЬ!) - PullRequest
1 голос
/ 17 октября 2011

Я написал функцию в 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

Элементы в первом столбце - единственные вещи, которые можно изменить.Элементы в трех других столбцах не должны изменяться.

Спасибо за помощь!

Ответы [ 2 ]

3 голосов
/ 17 октября 2011

проблема заключается в экранировании символа "\". Поэкспериментируйте с "\\ s" или даже "\\\\ s". Если вы не запускаете скрипт напрямую, символ «\» оценивается два раза: сначала оболочкой, а затем awk. В любом случае, ваше решение слишком сложное.

Попытка:

sed -i "s/^28 /METAL/" file

sed -i означает замену на месте, поэтому вам не нужно копировать файл "file" в "file.old", а затем обратно обратно в "file".

Zsh имеет встроенную функцию для экранирования строк:

f="to be escaped"
print ${(q)f}

HTH Крис

1 голос
/ 17 октября 2011

Если вы не можете выиграть, и цитирование ада сводит вас с ума (и вы знаете, что есть пробел, а не вкладка), просто обманывайте:

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/.

...