প্যারামিটারের প্রসারণে বাশ কি রেফারেন্সগুলিকে সমর্থন করে?


15

আমি নামক একটি পরিবর্তনশীল আছে descrযা একটি স্ট্রিং থাকতে পারে Blah: -> r1-ae0-2 / [123], -> s7-Gi0-0-1:1-US / Fooইত্যাদি আমি পেতে চাই -> r1-ae0-2, -> s7-Gi0-0-1:1-USস্ট্রিং থেকে অংশ। এই মুহুর্তে আমি এটির descr=$(grep -oP '\->\s*\S+' <<< "$descr"জন্য ব্যবহার করি । এই কাজ করতে একটি ভাল উপায় আছে কি? প্যারামিটার সম্প্রসারণের মাধ্যমে এটি করা কি সম্ভব?

উত্তর:


20

ksh93এবং zshপিছনে রেফারেন্স (বা আরও সঠিকভাবে 1 , প্রতিস্থাপনে গ্রুপগুলি ক্যাপচারের জন্য রেফারেন্স) এর ভিতরে সমর্থন রয়েছে ${var/pattern/replacement}, নেই bash

ksh93:

$ var='Blah: -> r1-ae0-2 / [123]'
$ printf '%s\n' "${var/*@(->*([[:space:]])+([^[:space:]]))*/\1}"
-> r1-ae0-2

zsh:

$ var='Blah: -> r1-ae0-2 / [123]'
$ set -o extendedglob
$ printf '%s\n' "${var/(#b)*(->[[:space:]]#[^[:space:]]##)*/$match[1]}"
-> r1-ae0-2

( mkshম্যান পৃষ্ঠাতেও উল্লেখ করা হয়েছে যে ভবিষ্যতের সংস্করণগুলি ${KSH_MATCH[1]}প্রথম ক্যাপচার গ্রুপের সাথে এটি সমর্থন করবে 2017 2017-04-25 পর্যন্ত এখনও উপলভ্য নয়)।

তবে, এর সাথে bash, আপনি এটি করতে পারেন:

$ [[ $var =~ -\>[[:space:]]*[^[:space:]]+ ]] &&
  printf '%s\n' "${BASH_REMATCH[0]}"
-> r1-ae0-2

এটিটি নিখুঁতভাবে খুঁজে পাওয়া যায় নি যাচাই করে যা ভাল।

যদি আপনার সিস্টেমে রিজেক্সপ্স সমর্থন করে \s/ \S, আপনি এটি করতে পারেন:

re='->\s*\S+'
[[ $var =~ $re ]]

এর সাথে zsh, আপনি এতে পিসিআরই এর সম্পূর্ণ ক্ষমতা পেতে পারেন:

$ set -o rematchpcre
$ [[ $var =~ '->\s*\S+' ]] && printf '%s\n' $MATCH
-> r1-ae0-2

সহ zsh -o extendedglob, আরও দেখুন:

$ printf '%s\n' ${(SM)var##-\>[[:space:]]#[^[:space:]]##}
-> r1-ae0-2

Portably:

$ expr " $var" : '.*\(->[[:space:]]*[^[:space:]]\{1,\}\)'
-> r1-ae0-2

স্ট্রিংয়ে প্যাটার্নটির বেশ কয়েকটি ঘটনা উপস্থিত থাকলে, সমস্ত সমাধানগুলির সাথে আচরণটি পৃথক হবে। তবে এগুলির কোনওটিই আপনাকে আপনার জিএনইউ- grepভিত্তিক সমাধানের মতো সমস্ত মিলের নতুন লাইনের দ্বারা পৃথক তালিকা দেবে না ।

এটি করার জন্য, আপনাকে হাত দিয়ে লুপিং করতে হবে। উদাহরণস্বরূপ, এর সাথে bash:

re='(->\s*\S+)(.*)'
while [[ $var =~ $re ]]; do
  printf '%s\n' "${BASH_REMATCH[1]}"
  var=${BASH_REMATCH[2]}
done

এর সাথে zsh, আপনি সমস্ত ম্যাচকে অ্যারেতে সঞ্চয় করতে এই ধরণের কৌশলটি অবলম্বন করতে পারেন:

set -o extendedglob
matches=() n=0
: ${var//(#m)->[[:space:]]#[^[:space:]]##/${matches[++n]::=$MATCH}}
printf '%s\n' $matches

1 ব্যাক-রেফারেন্স আরও সাধারণভাবে একটি প্যাটার্ন নির্দিষ্ট করে যা পূর্ববর্তী গোষ্ঠীর সাথে কী মিলছিল re উদাহরণস্বরূপ, \(.\)\1মৌলিক নিয়মিত অভিব্যক্তি একই অক্ষরটির পরে একক অক্ষরের সাথে মেলে (এটি মেলে aa, চালু নয় ab)। যে \1একটি যে ব্যাক-রেফারেন্স \(.\)একই প্যাটার্ন ক্যাপচার গ্রুপ।

ksh93এর নিদর্শনগুলিতে ব্যাক-রেফারেন্সগুলিকে সমর্থন করে (উদাহরণস্বরূপ ls -d -- @(?)\1ফাইলের নাম তালিকাভুক্ত করা হবে যা দুটি অভিন্ন অক্ষর নিয়ে গঠিত), অন্য শেল নয় not স্ট্যান্ডার্ড BREs এবং PCREs ব্যাক-রেফারেন্সগুলিকে সমর্থন করে তবে স্ট্যান্ডার্ড ERE নয়, যদিও কিছু ERE বাস্তবায়ন এটিকে এক্সটেনশান হিসাবে সমর্থন করে extension bashএর আগে [[ foo =~ re ]]ব্যবহার করে।

[[ aa =~ (.)\1 ]]

মিলবে না, তবে

re='(.)\1'; [[ aa =~ $re ]]

যদি সিস্টেমের EREs এটি সমর্থন করে।


9

আপনি প্রথম অবধি সমস্ত কিছু মুছতে চান ␣->␣("তীর" সহ নয়) এবং শেষের পরে ␣/(স্থান এবং স্ল্যাশ সহ)।

string="Blah: -> r1-ae0-2 / [123]"
string=${string/*->/->}
string=${string/ \/*}

$stringএখন হবে -> r1-ae0-2

একই দুটি বিকল্প রূপান্তরিত -> s7-Gi0-0-1:1-US / Fooহবে -> s7-Gi0-0-1:1-US


3

প্রতিটি বার্তা সঠিক ফর্ম্যাটটি না জেনে এটির যথাযথভাবে উত্তর দেওয়া অসম্ভব । তবে, সাধারণ পদ্ধতির হিসাবে আপনি নির্দিষ্ট কিছু ক্ষেত্রগুলি ব্যবহার করে মুদ্রণ করতে পারেন cut:

$ cut -d ' ' -f 2 <<< '-> s7-Gi0-0-1:1-US / Foo'
s7-Gi0-0-1:1-US

অথবা আপনি প্রতিটি নবম কলামটি ব্যবহার করে মুদ্রণawk করতে পারেন :

$ awk -F' ' '{ for (i=2;i<=NF;i+=4) print $i }' <<< '-> r1-ae0-2 / [123], -> s7-Gi0-0-1:1-US / Foo'
r1-ae0-2
s7-Gi0-0-1:1-US
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.