1

** ' * *'でマークされたフォローアップの質問があります**

私は Perl コードを書くように頼まれました。これは、everyを{with{function(<counter>)に置き換え、すべての置換でカウンターが 1 大きくなるはずです。たとえば、1 回目の置換は{will {function(0) 、2 回目の置換は{will{function(1)などです。サブフォルダを含みます。*.c*.h

私はこのコードを書きました:

#!/usr/bin/perl
use Tie::File;
use File::Find;
$counter = 0;
$flag = 1;

@directories_to_search = 'd:\testing perl';
@newString = '{ function('.$counter.')';
$refChar = "{";
finddepth(\&fileMode, @directories_to_search);


sub fileMode 
{
 my @files = <*[ch]>;   # get all files ending in .c or .h
 foreach $file (@files) # go through all the .c and .h flies in the directory  
{
    if (-f $file)  # check if it is a file or dir
    {
    my @lines;
# copy each line from the text file to the string @lines and add a function call after every     '{' '
    tie @lines, 'Tie::File', $file or die "Can't read file: $!\n";
    foreach ( @lines )
    {
        if (s/{/@newString/g)
        {
            $counter++;
            @newString = '{function('.$counter.')';
        }
        untie @lines; # free @lines
    }
    }
}   
}

コードはディレクトリを検索して置換を行いますが、取得 するd:\testing Perl代わりに、取得 したい最初の置換を取得 します。{function(<number>){function(number1) function(number3) function(number5) function(number7){function(0) function(2) function(4) function(6){function(0)

私のコードの何が問題なのか本当にわかりません。

awk ソリューションまたはその他の Perl ソリューションも優れています。


* 追加の質問があります。同じ行に '{' と '}' がある場合は、perl プログラムが行を除くすべてのファイルで同じ置換を行うようにします
。だから私はこのようにコードを修正しました。

#!/usr/bin/perl

use strict;
use warnings;
use Tie::File;
use File::Find;

my $dir = "C:/test dir";   


# fill up our argument list with file names:
find(sub { if (-f && /\.[hc]$/) { push @ARGV, $File::Find::name } }, $dir);

$^I = ".bak";   # supply backup string to enable in-place edit 

my $counter = 0; 

# now process our files
#foreach $filename (@ARGV) 
while (<>) 
{
    my @lines;
    # copy each line from the text file to the string @lines and add a function call after every '{' '
    tie @lines, 'Tie::File', $ARGV or die "Can't read file: $!\n";
    #$_='{function(' . $counter++ . ')';

    foreach  (@lines) 
    {   
        if   (!( index (@lines,'}')!= -1 )) # if there is a '}' in the same line don't add the     macro
            {
                s/{/'{function(' . $counter++ . ')'/ge;
                print;
            }

    }
    untie @lines; # free @lines
}    

私がやろうとしていたのは、自分のディレクトリとサブディレクトリで見つけた @ARGV のすべてのファイルを調べ、*.c または *.h ファイルごとに行ごとに移動し、この行に '{ が含まれているかどうかを確認することです。 '。存在する場合、プログラムは '{' があるかどうかをチェックせず、置換を行いません。存在しない場合、プログラムは '{' を '{function();' に置き換えます。

残念ながら、このコードは機能しません。私はそれを一日中機能させようとしているのに、まだうまくいかないと言うのは恥ずかしい. 助けていただければ幸いです。

ありがとうございました!!

4

4 に答える 4

3

これは、検索方法とインプレース編集を組み合わせるという単純な問題です。を使用することもできますTie::Fileが、実際には同じ結果になります。また、言うまでもなく、変更は元に戻すことができないため、このような編集を行う場合は、常に元のファイルのバックアップを保持する必要があります。

したがって、再帰が必要ない場合、タスクは Unix/Linux スタイルで非常に単純です。

perl -pi -we 's/{/"{ function(" . $i++ . ")"/ge' *.h *.c

もちろん、Windows を使用しているように見えるため、cmdシェルは引数をグロブしないため、手動で行う必要があります。そして、引用符を変更する必要があります。-iまた、 (インプレース編集) スイッチのバックアップ引数を指定する必要があります。

perl -pi.bak -we "BEGIN { @ARGV = map glob, @ARGV }; s/{/'{ function(' . $i++ . ')'/ge" *.h *.c

これは、スクリプトを作成するのに十分な長さになりつつあります。

再帰が必要な場合は、 を使用しますFile::Find。このコードの機能は、上記のコードとほとんど同じであることに注意してください。

use strict;
use warnings;
use File::Find;

my $dir = "d:/testing perl";   # use forward slashes in paths

# fill up our argument list with file names:
find(sub { if (-f && /\.[hc]$/) { push @ARGV, $File::Find::name } }, $dir);

$^I = ".bak";   # supply backup string to enable in-place edit 

my $counter = 0; 

# now process our files
while (<>) {
    s/{/'{ function(' . $counter++ . ')'/ge;
    print;
}

バックアップ オプションについて誤った安心感に惑わされないでください。このスクリプトを 2 回続けて実行すると、それらのバックアップは上書きされるので、注意してください。

于 2013-01-09T13:16:40.313 に答える
2
$ perl -pi -e 's| (?<={) | q#function(# . ($i++) . q#)# |gex' *.c *.h
于 2013-01-09T13:08:18.847 に答える
1

これは、以下のように1行で実行できます。

perl -pi -e 's/({)/"{function(".++$a.")"/ge;' your_file

入力ファイルの例を取り、テストも行いました。

> cat temp
line-1 {    {    {   {
line-2 {    {   {
line-3 {    {
line-4 {

今実行:

> perl -pi -e 's/({)/"{function(".++$a.")"/ge;' temp
> cat temp
line-1 {function(1)    {function(2)    {function(3)   {function(4)
line-2 {function(5)    {function(6)   {function(7)
line-3 {function(8)    {function(9)
line-4 {function(10)
于 2013-01-09T13:21:02.807 に答える
1

awk '/{/{gsub(/{/,"{function("i++")");print;next}{print}'コードを入力として使用する:

$ awk '/{/{gsub(/{/,"{function("i++")");print;next}{print}' file
sub fileMode 
{function(0)
 my @files = <*[ch]>;   # get all files ending in .c or .h
 foreach $file (@files) # go through all the .c and .h flies in the directory  
{function(1)
    if (-f $file)  # check if it is a file or dir
    {function(2)
    my @lines;
# copy each line from the text file to the string @lines and add a function call after every     '{function(3)' '
    tie @lines, 'Tie::File', $file or die "Can't read file: $!\n";
    foreach ( @lines )
    {function(4)
        if (s/{function(5)/@newString/g)
        {function(6)
            $counter++;
            @newString = '{function(7)function('.$counter.')';
        }
        untie @lines; # free @lines
    }
    }
}   
}

注: インラインのネストされた関数の番号はインクリメントされません{

$ echo -e '{ { \n{\n-\n{' | awk '/{/{gsub(/{/,"{function("i++")");print;next}1'
{function(0) {function(0) 
{function(1)
-
{function(2)

説明:

/{/                               # For any lines that contain {
gsub( /{/ , "{function("i++")" )  # replace { with function(i++)
print;next # print the line where the replacement happened and skip to the next
print                             # print all the lines 
于 2013-01-09T12:51:27.077 に答える