3

正規表現(およびperl)を使用してファイルのリストを編集するコマンドを見つけました(そして少し調整しました)。これを というスクリプト ファイルに入れたので、現在のディレクトリ内のすべてのファイルで出現するすべての を に置き換えるcredことができます。cred . england EnglandenglandEngland

find $1 -type f -exec perl -e 's/'$2'/'$3'/g' -p -i {} \;

それは非常に強力で、すでに有用ですが、危険であり、欠陥があります。私はそれをしたい...

  1. 最初に変更 (または少なくとも操作されたファイル) をプレビューし、確認を求めます
  2. 単一の単語よりも長い文字列を処理します。試しcred . england 'the United Kingdom'ましたが失敗しました

同じことを達成するために、他の(短くて記憶に残る、osxおよびubuntuに普遍的にインストール/インストール可能な)コマンドにも興味があります。

編集:

これは私がこれまでに持っているものです-改善の余地があります...

# highlight the spots that will be modified (not specifying the file)
find $1 -type f -exec grep -E "$2" --color {} \;
# get confirmation
read -p "Are you sure? " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
  # make changes, and highlight the spots that were changed
  find $1 -type f -exec perl -e "s/$2/$3/g" -p -i {} \;
  echo ""
  find $1 -type f -exec grep -E "$3" --color {} \;
else
  echo ""
  echo "Aborted!!"
fi
4

2 に答える 2

3

スペースを含む文字列を操作するには、次のようにコマンドを記述します。

perl -e "s/$2/$3/g"

二重引用符を使用すると、変数は引用符内で展開されます。

変更のプレビューや確認の要求などを行うには、はるかに複雑なスクリプトが必要になります。非常に簡単な方法の 1 つはfind $1 -type f、最初に実行してすべてのファイルのリストを取得し、次にreadコマンドを使用して入力を取得し、続行するかどうかを決定することです。

于 2012-09-26T21:48:01.890 に答える
1

これは、File::Findを使用した純粋なPerlバージョンです。かなり長くなりますが、デバッグやより複雑な操作が簡単になります。また、ファイルごとに機能するため、検証を簡単に行うことができます。

use strict;
use warnings;

use autodie;
use File::Find;
use File::Temp;

my($Search, $Replace, $Dir) = @ARGV;

# Useful for testing
run($Dir);

sub run {
    my $dir = shift;
    find \&replace_with_verify, $dir;
}

sub replace_with_verify {
    my $file = $_;
    return unless -f $file;

    print "File: $file\n";

    if( verify($file, $Search) ) {
        replace($file, $Search, $Replace);
        print "\nReplaced: $file\n";
        highlight($file, $Replace);
    }
    else {
        print "Ignoring $file\n";
    }

    print "\n";
}

sub verify {
    my($file, $search) = @_;

    highlight($file, $search);

    print "Are you sure? [Yn] ";
    my $answer = <STDIN>;

    # default to yes
    return 0 if $answer =~ /^n/i;
    return 1;
}

sub replace {
    my($file, $search, $replace) = @_;

    open my $in, "<", $file;
    my $out = File::Temp->new;

    while(my $line = <$in>) {
        $line =~ s{$search}{$replace}g;
        print $out $line;
    }

    close $in;
    close $out;

    return rename $out->filename, $file;
}

sub highlight {
    my($file, $pattern) = @_;

    # Use PCRE grep.  Should probably just do it in Perl to ensure accuracy.
    system "grep", "-P", "--color", $pattern, $file;    # Should probably use a pager
}
于 2012-09-27T02:53:31.690 に答える