পাওয়ারশেল ব্যবহার করে কোনও ফাইলে একাধিক স্ট্রিং কীভাবে প্রতিস্থাপন করা যায়


106

আমি একটি কনফিগারেশন ফাইল কাস্টমাইজ করার জন্য একটি স্ক্রিপ্ট লিখছি। আমি এই ফাইলটির মধ্যে একাধিক স্ট্রিং প্রতিস্থাপন করতে চাই এবং কাজটি করার জন্য আমি পাওয়ারশেল ব্যবহার করে চেষ্টা করেছি।

এটি একটি একক প্রতিস্থাপনের জন্য দুর্দান্ত কাজ করে তবে একাধিক প্রতিস্থাপন করা খুব ধীর কারণ প্রতিবার এটি পুরো ফাইলটিকে আবার বিশ্লেষণ করতে হয় এবং এই ফাইলটি খুব বড়। স্ক্রিপ্টটি দেখতে এমন দেখাচ্ছে:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1new'
    } | Set-Content $destination_file

আমি এরকম কিছু চাই, তবে কীভাবে এটি লিখতে হয় তা আমি জানি না:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa'
    $_ -replace 'something2', 'something2bb'
    $_ -replace 'something3', 'something3cc'
    $_ -replace 'something4', 'something4dd'
    $_ -replace 'something5', 'something5dsf'
    $_ -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file

উত্তর:


167

এক বিকল্প -replaceঅপারেশন একসাথে চেইন হয় । `প্রতিটি লাইনে শেষে সম্পর্কে newline পালাতে, পরবর্তী লাইনে অভিব্যক্তি পার্স অব্যাহত রাখার জন্য PowerShell ঘটাচ্ছে:

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'
(Get-Content $original_file) | Foreach-Object {
    $_ -replace 'something1', 'something1aa' `
       -replace 'something2', 'something2bb' `
       -replace 'something3', 'something3cc' `
       -replace 'something4', 'something4dd' `
       -replace 'something5', 'something5dsf' `
       -replace 'something6', 'something6dfsfds'
    } | Set-Content $destination_file

অন্য বিকল্পটি একটি মধ্যবর্তী ভেরিয়েবল বরাদ্দ করা হবে:

$x = $_ -replace 'something1', 'something1aa'
$x = $x -replace 'something2', 'something2bb'
...
$x

$ Original_file == $ গন্তব্য_ফিল করতে পারে? আমি কি আমার উত্স হিসাবে একই ফাইলটি পরিবর্তন করছি?
cquadrini

পাওয়ারশেল সেমিডলেটগুলি যেভাবে তাদের ইনপুট / আউটপুট প্রবাহিত করে, তাই আমি বিশ্বাস করি না যে এটি একই পাইপলাইনে একই ফাইলটিতে লেখার জন্য কাজ করবে। যাইহোক, আপনি যেমন কিছু করতে পারে $c = Get-Content $original_file; $c | ... | Set-Content $original_file
dahlbyk

আসল এনকোডিংয়ের বিষয়বস্তু না থাকা সেট-সামগ্রী ব্যবহার করে ফাইল এনকোডিং সম্পর্কে আপনার কি সমস্যা আছে ? উদাহরণস্বরূপ ইউটিএফ -8 বা এএনএসআই এনকোডিং।
কিকিনেট

1
হ্যা পাওয়ারশেল ... এমন অসহায়। আপনাকে নিজের এনকোডিং সনাক্ত করতে হবে, যেমন github.com/dahlbyk/posh-git/blob/…
dahlbyk

24

জর্জ হাওয়ার্থের একাধিক প্রতিস্থাপনের সাথে সঠিকভাবে কাজ করার জন্য আপনাকে ব্রেকটি সরিয়ে ফেলতে হবে, একটি ভেরিয়েবলের (আউটপুট) আউটপুট বরাদ্দ করতে হবে এবং তারপরে ভেরিয়েবলটি আউটপুট দিতে হবে:

$lookupTable = @{
    'something1' = 'something1aa'
    'something2' = 'something2bb'
    'something3' = 'something3cc'
    'something4' = 'something4dd'
    'something5' = 'something5dsf'
    'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object {
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line = $line -replace $_.Key, $_.Value
        }
    }
   $line
} | Set-Content -Path $destination_file

এটি এখন পর্যন্ত আমি দেখি সেরা পন্থা। একমাত্র সমস্যাটি হ'ল একই উত্স / গন্তব্য ফাইলের পাথগুলি ব্যবহার করার জন্য আমাকে প্রথমে সম্পূর্ণ ফাইল সামগ্রীটি একটি চলকটিতে পড়তে হয়েছিল।
এঙ্গুলারসেন

এটি সেরা উত্তরের মতো দেখাচ্ছে, যদিও আমি এর সাথে কিছু অদ্ভুত আচরণ ভুলরূপে মেলে। যেমন আপনার ক্ষেত্রে স্ট্রিং হিসাবে হেক্স মান সহ একটি হ্যাশ টেবিল রয়েছে (0x0, 0x1, 0x100, 0x10000) এবং 0x10000 0x1 এর সাথে মিলবে।
Lorek

13

পাওয়ারশেলের 3 সংস্করণ সহ আপনি একসাথে প্রতিস্থাপন কলগুলি চেইন করতে পারেন:

 (Get-Content $sourceFile) | ForEach-Object {
    $_.replace('something1', 'something1').replace('somethingElse1', 'somethingElse2')
 } | Set-Content $destinationFile

সূক্ষ্ম + সাবলীল স্বাদে কাজ করে
hdoghmen

10

ধরে নিই যে আপনার কাছে প্রতি লাইনে একটি 'something1'বা এক 'something2'ইত্যাদি থাকতে পারে, আপনি একটি সারণী ব্যবহার করতে পারেন:

$lookupTable = @{
    'something1' = 'something1aa'
    'something2' = 'something2bb'
    'something3' = 'something3cc'
    'something4' = 'something4dd'
    'something5' = 'something5dsf'
    'something6' = 'something6dfsfds'
}

$original_file = 'path\filename.abc'
$destination_file =  'path\filename.abc.new'

Get-Content -Path $original_file | ForEach-Object {
    $line = $_

    $lookupTable.GetEnumerator() | ForEach-Object {
        if ($line -match $_.Key)
        {
            $line -replace $_.Key, $_.Value
            break
        }
    }
} | Set-Content -Path $destination_file

আপনি ঐ একাধিক থাকতে পারে, তাহলে শুধু অপসারণ breakমধ্যে ifবিবৃতি।


আমি দেখছি ট্রয়ব্র্যামলি কোনও লাইনের লেখার জন্য শেষ লাইনের ঠিক আগে before লাইন যুক্ত করেছে যার কোনও পরিবর্তন নেই। ঠিক আছে. আমার ক্ষেত্রে আমি প্রতিস্থাপনের জন্য প্রয়োজনীয় প্রতিটি লাইনে পরিবর্তন করেছি।
ক্লিফক্লফ

8

একটি তৃতীয় বিকল্প, একটি পাইপলাইনযুক্ত এক-লাইনারের জন্য -স্থানীয় স্থানগুলিতে বাসা বাঁধাই:

PS> ("ABC" -replace "B","C") -replace "C","D"
ADD

এবং:

PS> ("ABC" -replace "C","D") -replace "B","C"
ACD

এটি এক্সিকিউশন অর্ডার সংরক্ষণ করে, পড়তে সহজ, এবং পাইপলাইনে খুব সুন্দরভাবে ফিট করে। আমি সুস্পষ্ট নিয়ন্ত্রণ, স্ব-ডকুমেন্টেশন ইত্যাদির জন্য প্রথম বন্ধনী ব্যবহার করতে পছন্দ করি এটি এগুলি ব্যতীত কাজ করে তবে আপনি কতটা বিশ্বাস করেন?

- রিপ্লেস একটি তুলনা অপারেটর, যা কোনও বস্তুকে গ্রহণ করে এবং সম্ভবত পরিবর্তিত অবজেক্টটি প্রদান করে। এই কারণেই আপনি উপরের মতো দেখিয়েছেন বা এগুলি স্ট্যাক বা বাসাতে পারেন।

দয়া করে দেখুন:

help about_operators
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.