2015-10-24 3 views
0

у меня есть список файлов, как показано ниже:Использование СЭД в цикле для поиска и замены нескольких файлов

RF1.lib 
RF2.lib 
RF3.lib 
etc.. 

В каждом из *.lib файлов я должен заменить эту строку vlib с именем файла, как RF1 , RF2 и т.д.

Я использую команду sed для поиска и замены строки, как показано ниже:

sed -i -e 's/vlib/RF1/g' RF1.lib 

sed -i -e 's/vlib/RF2/g' RF2.lib 

Но мне нужно сделать это несколько раз для поиска и замены для каждого файла.

Есть ли способ открыть файлы в цикле и использовать команду sed для замены в каждом файле?

+0

Замена зависит от имени файла. – Sobrique

ответ

0

Вот скрипт на Perl, который заменит строку в каждом файле с именем файла:

#!/usr/bin/perl 
use warnings; 
use strict; 

foreach my $file (glob "/path/to/dir/*.lib") #get all the '.lib' files from dir 
{ 
    my ($filename) = $file =~ m/([^\/]+)\.lib$/; #get the filename 
    open my $fh, "<", $file or die $!; 
    my @data = <$fh>; 
    close $fh; 
    foreach my $line (@data) 
    { 
     $line =~ s/\bvlib\b/$filename/g; #replace string with filename 
    } 
    #modify the file 
    open my $fhw, ">", $file or die "Couldn't modify file: $!"; 
    print $fhw @data; 
    close $fhw; 
} 

Edit: Как Бородин предложил в комментарии, читать весь файл в скалярное:

foreach my $file (glob "/path/to/dir/*.lib") #get all the '.lib' files from dir 
{ 
    my ($filename) = $file =~ m/([^\/]+)\.lib$/; #get the filename 

    #read whole file in a scalar 
    my $data = do { 
     local $/ = undef; 
     open my $fh, "<", $file or die $!; 
     <$fh>; 
    }; 
    $data =~ s/\bvlib\b/$filename/g; #replace string with filename 

    #modify the file 
    open my $fhw, ">", $file or die "Couldn't modify file: $!"; 
    print $fhw $data; 
    close $fhw; 
} 
+0

Не могли бы вы просто открыть '$ file' для вывода? – Sobrique

+0

@Sobrique: Хорошая точка. Спасибо, Обновлен в ответ. :) – serenesat

+0

Нет необходимости хранить две копии данных из файла. Вы также можете просто изменить '@ data' на месте. И пока мы на нем, хранение данных в массиве заставляет вас использовать цикл для его изменения. Если вы прочитаете весь файл в скаляр, то вы можете внести изменения в одну операцию. Вероятно, лучше всего использовать шаблон '\ bvlib \ b', чтобы избежать кратковременных контуров чего-то вроде' navlib' – Borodin

0

Несомненно. Вы можете сказать:

for f1 in RF*.lib: do 
    j=`basemame $f1 .lib` 
    sed -i -e "s/vlib/$j/g" $f1 
done 
+0

Привет, Сурешвв, я новичок в perl. Когда я использую это в perl-скрипте, я получаю сообщение об ошибке «Отсутствует переменная $ on loop в строке 3». Пожалуйста, не могли бы вы сообщить мне, что не так? – Rach

+0

Это потому, что это не скрипт perl, это оболочка. – Sobrique

+0

Да. Как говорит @Sobrique, это всего лишь сценарий оболочки, который можно запустить из командной строки. – sureshvv

0

Это может работать для вас (GNU СЭД):

sed -r 's|(.*)\.*|sed -i "s/vlib/\1/g" &|e' fileOfFiles 

Это оценивает команду sed для каждого из файлов в файле, содержащем файлы. Если вы предпочитаете, что выход команды может быть передан в оболочку для такого же эффекта, например:

sed -r 's|(.*)\.*|sed -i "s/vlib/\1/g" &|' fileOfFiles | sh 
+0

Спасибо Потонг. это работает, но вместо замены «vlib» на «RF1» он заменяет vlib «RF1.lib» и т. д. – Rach

Смежные вопросы