URL: https://www.opennet.dev/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 96833
[ Назад ]

Исходное сообщение
"Замена строки в файле"

Отправлено VladiS , 02-Мрт-17 19:57 
Привет, камрады!

Есть питоновские файлы 200 штук. Нужно в конкретном классе поменять "return self.name" на  "return self.displayname". Проблема в том, что "return self.name" около 10-15шт, а нужна конкретная. Помогите.

Руками не кошерно.


Содержание

Сообщения в этом обсуждении
"Замена строки в файле"
Отправлено Аноним , 02-Мрт-17 20:12 
> Привет, камрады!
> Есть питоновский файлы 200 штук. Нужно в конкретном классе поменять "return self.name"
> на  "return self.displayname". Проблема в том, что "return self.name" около
> 10-15шт, а нужна конкретная. Помогите.
> Руками не кошерно.

ну так конкретная должна быть привязана к какой-то конкретной строке, до или после
внимание вопрос - к какой?

имя сестра, имя! (с) ☺


"Замена строки в файле"
Отправлено VladiS , 02-Мрт-17 20:19 
>> Привет, камрады!
>> Есть питоновский файлы 200 штук. Нужно в конкретном классе поменять "return self.name"
>> на  "return self.displayname". Проблема в том, что "return self.name" около
>> 10-15шт, а нужна конкретная. Помогите.
>> Руками не кошерно.
> ну так конкретная должна быть привязана к какой-то конкретной строке, до или
> после
> внимание вопрос - к какой?
> имя сестра, имя! (с) ☺

Согласен, плохо объяснил.

    class Meta:
        db_table = u'type' - уникальная строка

    def __unicode__(self):
          return self.name - нужно поменять


"Замена строки в файле"
Отправлено каукасец , 02-Мрт-17 23:52 
что-то вроде этого (где "type" - уникальная строка):

grep -R -l type . | xargs sed -i 's/self.name/self.displayname/g'


"Замена строки в файле"
Отправлено VladiS , 03-Мрт-17 00:25 
> что-то вроде этого (где "type" - уникальная строка):
> grep -R -l type . | xargs sed -i 's/self.name/self.displayname/g'

Твоя строка находит все файлы в которых есть уникальная строка (допустим это правильно), но потом она меняет ВСЕ "self.name" в файле на "self.displayname". А мне же нужно поменять "self.name" только рядом с уникальной строкой.

Файлов много, уникальная строка не везде на одном номере строки.
Можно и руками, но мне же хочется решить задачу автоматизированно. На С вопрос решиться сравнением строк, а вот на Bash я не умею, но что-то подсказывает это проще чем мне кажется.

Можно ли на bash найти уникальную строчку и после нее сделать первую и единственную замену  "self.name" на "self.displayname"?


"Замена строки в файле"
Отправлено ACCA , 03-Мрт-17 01:52 
> Есть питоновские файлы 200 штук. Нужно в конкретном классе поменять "return self.name"
> на  "return self.displayname". Проблема в том, что "return self.name" около
> 10-15шт, а нужна конкретная. Помогите.
> Руками не кошерно.

№1 - сэкономит ли программа больше времени, чем ушло на её написание? Если нет, зачем её писать?

№2 - на Perl это делается так:


perl -pe 's/return self.name/return self.displayname/g if /^class Meta/ .. /^class (?!Meta)/;' filename.py

Ограничение - class Meta должен быть не последним в файле filename.py.


"Замена строки в файле"
Отправлено VladiS , 03-Мрт-17 13:21 
>[оверквотинг удален]
>> 10-15шт, а нужна конкретная. Помогите.
>> Руками не кошерно.
> №1 - сэкономит ли программа больше времени, чем ушло на её написание?
> Если нет, зачем её писать?
> №2 - на Perl это делается так:
>
 
> perl -pe 's/return self.name/return self.displayname/g if /^class Meta/ .. /^class (?!Meta)/;'
> filename.py
>

> Ограничение - class Meta должен быть не последним в файле filename.py.

№1 - поэтому и прошу помощи
№2 - что-то не отработало. Попробую пошаманить.


"Замена строки в файле"
Отправлено ACCA , 03-Мрт-17 20:46 
> №2 - что-то не отработало. Попробую пошаманить.

Оно не меняет сам файл, оно вываливает в stdout новое содержимое. Что с ним делать - вопрос второй (т.е. перехватывай stdout и складывай куда хочешь).

Например:

mkdir src.new
find src.old -name '*py' | while read srcname
do
   perl -pe 's/return self.name/return self.displayname/g if /^class Meta/ .. /^class (?!Meta)/;' $srcname > src.new/$(basename $srcname)
done

С подкаталогами тоже нужно что-то делать. См.№1


"Замена строки в файле"
Отправлено VladiS , 03-Мрт-17 21:26 
>[оверквотинг удален]
> с ним делать - вопрос второй (т.е. перехватывай stdout и складывай
> куда хочешь).
> Например:
> mkdir src.new
> find src.old -name '*py' | while read srcname
> do
>    perl -pe 's/return self.name/return self.displayname/g if /^class Meta/ ..
> /^class (?!Meta)/;' $srcname > src.new/$(basename $srcname)
> done
> С подкаталогами тоже нужно что-то делать. См.№1

Спасибо! Написал на С. ))


"Замена строки в файле"
Отправлено михалыч , 03-Мрт-17 21:50 
>[оверквотинг удален]
>> куда хочешь).
>> Например:
>> mkdir src.new
>> find src.old -name '*py' | while read srcname
>> do
>>    perl -pe 's/return self.name/return self.displayname/g if /^class Meta/ ..
>> /^class (?!Meta)/;' $srcname > src.new/$(basename $srcname)
>> done
>> С подкаталогами тоже нужно что-то делать. См.№1
> Спасибо! Написал на С. ))

ну ты конкретно кросавчег, просто какой-то монстр ))


"Замена строки в файле"
Отправлено ACCA , 04-Мрт-17 07:12 
> Спасибо! Написал на С. ))

Иногда усердие превозмогает разум. (с)


"Замена строки в файле"
Отправлено михалыч , 03-Мрт-17 21:39 
> что-то не отработало

и у меня,
но идея подана

попробуем так, прямолинейно


#!/usr/bin/perl

$file = shift;

open FH, $file;

$pat1 = 'db_table = u\'type\'';

while (<FH>) {
    next unless /$pat1/;
    next unless $_ = <FH> and $_ =~ /^$/;
    next unless $_ = <FH> and $_ =~ /\S+/;
    next unless $_ = <FH> and $_ =~ /self\.name/;
    # если после изменяемой строки нет пустой строки, то следующую строку закоментить
    next unless $_ = <FH> and $_ =~ /^$/;
    next unless $_ = <FH>;
    $pat2 = $_;
}

close FH;

open FH, $file;

while (<FH>) {
    s/self\.name/self\.displayname/ if /$pat1/ .. /$pat2/;
    print;
}

close FH;


использовать так
./script.pl /in/file.old > /out/file.new


"Замена строки в файле"
Отправлено ACCA , 04-Мрт-17 07:30 
>> что-то не отработало
> и у меня,
> но идея подана

[...]

Улучшения улучшений не следует петь и танцевать.

>     # если после изменяемой строки нет пустой строки,
> то следующую строку закоментить

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

>     $pat2 = $_;

Теперь представь, что у тебя попалась такая конструкция


   x = x +1
   self.name .= x
   y = y -2
   self.name .= y
   return self.name

> close FH;
> open FH, $file;

В приличных местах это делается с помощью seek.


"Замена строки в файле"
Отправлено михалыч , 04-Мрт-17 09:30 
> Улучшения улучшений не следует петь и танцевать.

ладно! построю свой лунапарк

#!/usr/bin/perl

while (<>) {
    print;
    next unless /db_table = u'type'/;
    next unless $_ = <> and /^$/;
    print;
    next unless $_ = <> and /\w+/;
    print;
    next unless $_ = <>;
    s/name/displayname/;
    print;
}

с блэкджеком и шлюxaми ))

"Замена строки в файле"
Отправлено михалыч , 05-Мрт-17 12:26 
continue to build Luna Park ))

сразу хочу заметить, что всё дальнейшее уже для ТС не актуально, он уже решение для себя на Сях написал
но вдруг кому пригодится, хотя у меня конечно есть сильное подозрение, что это такой секрет Полишинеля ))

итак, есть какой-либо текст и в нём нужно заменить/удалить какой-либо фрагмент текста или слово
причём этот фрагмент текста или слово повторяется в тексте неоднократно
но удаление/замену нужно выполнить после определённого текста/слова в данном тексте

например в следующем тексте нужно заменить слово cat на слово DOG
но заменить нужно первое вхождение после определённого текста,
в данном случае пусть это будет слово replace

it is a simple text containing the word cat and other words
the word cat is found in this text several times

this text is divided into several paragraphs
this is the word cat and the word cat yet

need to replace the word cat with the word DOG
but you need to replace the first occurrence of the word cat after the word "replace"

please do not touch the other cats

the other words in the text of the cat does not replace
the rest of the text remains unchanged

для того чтобы прочесть текст одним куском установим разделитель в неопределённое значение

#!/usr/bin/perl

local $/ = undef;
$file = <>;
$file =~ s/(replace(?:(?!cat)).*?)cat/$1DOG/s;
print $file;

ну и разумеется, однострочник, куда же без него ))

нужно использовать ключик -0777 чтобы заставить читать весь файл сразу одним куском
ну и знак "!" в FreeBSD необходимо экранировать

получится

perl -0777 -pe 's/(replace(?:(?\!\cat)).*?)cat/$1DOG/s' text

а так можно заменить/удалить просто первое вхождение кота
perl -0777 -pe 's/((?:(?\!\cat)).*?)cat/$1DOG/s' text

возвращаясь к первоначальной задаче топикстартера всё это приобретает следующий вид

#!/usr/bin/perl

local $/ = undef;
$file = <>;
$file =~ s/(db_table\s=\su'type'(?:(?!self\.name)).*?)self\.name/$1self\.displayname/s;
print $file;

и это всё без регистрации и смс, безо всяких там условностей и ограничений ))

в однострочном варианте выглядит не так красиво и изящно как хотелось бы, вылезают косяки с одинарными кавычками
решение подсмотрел здесь же на opennet'е ==> http://www.opennet.dev/tips/info/2393.shtml

env re="'" perl -0777 -pe 's/(db_table = u$ENV{re}type$ENV{re}(?:(?\!self\.name)).*?)self\.name/$1self\.displayname/s' txt

использование -i.bak заставит perl переписать исходный текст и скопировать исходный вариант в файл txt.bak
env re="'" perl -i.bak -0777 -pe 's/(db_table = u$ENV{re}type$ENV{re}(?:(?\!self\.name)).*?)self\.name/$1self\.displayname/s' txt

повторю - это уже неважно, но всё же, вдруг пригодится кому-то ещё

такие дела


"Замена строки в файле"
Отправлено VladiS , 13-Сен-17 21:52 
Почему не важно? Я вот прочитал и для себя сделал пометочку.
Спасибо.