Найти и заменить числа в нескольких текстовых файлах с исходным измененным числом?

Я должен найти все строки "5dp" и заменить их с" (5*0.83) разность потенциалов", округленный в меньшую сторону до целых чисел. Номер 5 мог быть любым числом, и выражение в скобках на самом деле выполняется.

Например: 31dp должен стать 25dp.

Я должен искать все файлы в каталоге и подкаталогах рекурсивно. Какая-либо справка?

2
задан 10 September 2015 в 21:16

3 ответа

Используя find + Perl:

find . -type f -exec \
perl -i -e 'use POSIX;' -pe 's/([0-9]*)dp/floor($1*.83).dp/ge' {} +

find команда:

  • .: поиски в текущей рабочей иерархии каталогов;
  • -type f: поиски только файлов;
  • -exec [...] {} +: выполняет следующую команду, подающую его результаты поиска как список аргументов;

Команда Perl:

  • -i: указывает что файлы, обработанные <> конструкция должна быть отредактирована оперативная;
  • -p: Perl причин для принятия следующего цикла вокруг программы, которая заставляет его выполнить итерации по аргументам имени файла несколько как sed: while (<>) {...} continue {print or die "-p destination: $!\n";};
  • -e: используемый для ввода одной строки программы; Perl не будет искать имя файла в списке аргументов;

Разбивка Perl команда № 1:

  • use POSIX;: импорт POSIX модуль, необходимый для POSIX::floor функция;

Разбивка Perl команда № 2:

  • s: утверждает для выполнения замены
  • /: останавливается команда / запускает шаблон
  • (: запускает группу фиксации
  • [0-9]*: соответствия любое количество любой цифры
  • ): останавливает группу фиксации
  • dp: соответствия a dp строка
  • /: останавливается шаблон / запускает замещающую строку
  • floor($1*.83).dp: Выражение Perl, замененное результатом floor($1*.83) (где $1 полученная группа), сопровождаемый a dp строка
  • /: останавливается замещающая строка / запускает опции
  • g: утверждает для выполнения замен глобально
  • e: утверждает для выполнения замещающей строки как команды Perl

Демонстрационный вывод:

ubuntu@ubuntu:~/tmp$ tree
.
└── 1
    ├── 2
    │  ├── 3
    │  │  └── infile
    │  └── infile
    └── infile

3 directories, 3 files
ubuntu@ubuntu:~/tmp$ find . -type f -exec bash -c 'echo -e "{}:\n\n$(cat {})\n"' \;
./1/infile:

1dp 2dp 3dp 4dp 5dp
6dp 7dp 8dp 9dp 10dp
11dp 12dp 13dp 14dp 15dp

./1/2/infile:

1dp 2dp 3dp 4dp 5dp
6dp 7dp 8dp 9dp 10dp
11dp 12dp 13dp 14dp 15dp

./1/2/3/infile:

1dp 2dp 3dp 4dp 5dp
6dp 7dp 8dp 9dp 10dp
11dp 12dp 13dp 14dp 15dp

ubuntu@ubuntu:~/tmp$ find . -type f -exec perl -i -e 'use POSIX;' -pe 's/([0-9]*)dp/floor($1*.83).dp/ge' {} +
ubuntu@ubuntu:~/tmp$ find . -type f -exec bash -c 'echo -e "{}:\n\n$(cat {})\n"' \;
./1/infile:

0dp 1dp 2dp 3dp 4dp
4dp 5dp 6dp 7dp 8dp
9dp 9dp 10dp 11dp 12dp

./1/2/infile:

0dp 1dp 2dp 3dp 4dp
4dp 5dp 6dp 7dp 8dp
9dp 9dp 10dp 11dp 12dp

./1/2/3/infile:

0dp 1dp 2dp 3dp 4dp
4dp 5dp 6dp 7dp 8dp
9dp 9dp 10dp 11dp 12dp
1
ответ дан 2 December 2019 в 03:52

FWIW, вот решение с остротами удара:

(Имел тот, готовый, прежде чем я считал OP, хотел, чтобы целые числа, в конце концов, таким образом использование до н.э сделали математику плавающую.)

find . -type f|while read f;do cat "$f"|while read a;do b=`echo "$a"|sed 's/.*\([0-9]\+\)dp.*/\1*0.83/'|bc`;echo "$a"|sed s/"[0-9]\+dp"/"$b"dp/;done;done

... и округленный в меньшую сторону:

find . -type f|while read f;do cat "$f"|while read a;do b=`echo "$a"|sed 's/.*\([0-9]\+\)dp.*/\1*0.83/'|bc`;b=${b%.*};echo "$a"|sed s/"[0-9]\+dp"/"$b"dp/;done;done
0
ответ дан 2 December 2019 в 03:52

Намного более подробный: сценарий Python ниже:

#!/usr/bin/env python3
import os
import sys

directory = sys.argv[1]

for root, dirs, files in os.walk(directory):
    for file in files:
        subject = root+"/"+file
        text = open(subject).read().split(" ")
        for i, s in enumerate(text):
            if s.endswith("dp"):
                try:
                    n = str(int(float(s.replace("dp", ""))*0.83))+"dp"; text[i] = n
                except ValueError:
                    pass
        open(subject, "wt").write((" ").join(text))

Как использовать его

  • Скопируйте сценарий в пустой файл, сохраните его как replace_numbers.py
  • Выполните его командой:

    python3 /path/to/replace_numbers.py <directory>
    

Пример

a monkey eats 234dp bananas, while 2657dp would be too much. 234 is more the 12.

становится:

a monkey eats 194dp bananas, while 2205dp would be too much. 234 is more the 12.

Объяснение:

  • Сценарий открывает все файлы в каталоге (один за другим), читает их и разделяет его на строки.
  • ЕСЛИ "разность потенциалов" находится в строке, она разделяет число от "разности потенциалов", (попытки) умножить его на 0.83. Затем плавание округляется в меньшую сторону (использование int(<float>)). Если строка, разделенная от "разности потенциалов", кажется, не только число, процесс пропускается для определенной строки (предоставление a ValueError)
  • После того как все случаи "разности потенциалов" передаются, текст с замененными числами записан в файл снова, заменив оригинальный текст.
1
ответ дан 2 December 2019 в 03:52

Другие вопросы по тегам:

Похожие вопросы: