শেলটিতে একটি স্ট্রিং কীভাবে বিভক্ত করবেন এবং শেষ ক্ষেত্রটি পাবেন


292

ধরুন আমার কাছে স্ট্রিং রয়েছে 1:2:3:4:5এবং আমি এর শেষ ক্ষেত্রটি পেতে চাই ( 5এই ক্ষেত্রে)। আমি কীভাবে ব্যাশ ব্যবহার করে তা করব? আমি চেষ্টা করেছি cut, তবে শেষের ক্ষেত্রটি কীভাবে নির্দিষ্ট করতে হবে তা আমি জানি না -f

উত্তর:


429

আপনি স্ট্রিং অপারেটরগুলি ব্যবহার করতে পারেন :

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5

এটি সামনে থেকে '': অবধি লোভের সাথে সমস্ত কিছু ছাঁটাই করে।

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }

7
এটি প্রদত্ত সমস্যাটির জন্য কাজ করার সময়, নীচের উইলিয়ামের উত্তর ( স্ট্যাকওভারফ্লো.com / a / 3163857 / 520162 ) 5স্ট্রিং থাকলে 1:2:3:4:5:(স্ট্রিং অপারেটরগুলি খালি ফলাফল উপস্থাপন করলে) ফিরে আসে। সমাপ্তি /অক্ষর (বা না) থাকতে পারে এমন পাথগুলি পার্স করার সময় এটি বিশেষত সহজ ।

9
তাহলে কীভাবে আপনি এর বিপরীতে করবেন? '1: 2: 3: 4:' প্রতিধ্বনিত করতে?
ডবজ

11
এবং একজন কীভাবে শেষ বিভাজকের আগে অংশটি রাখে? স্পষ্টত ব্যবহার করে ${foo%:*}#- শুরু থেকে; %- শেষ থেকে। #, %- সংক্ষিপ্ততম ম্যাচ; ##, %%- দীর্ঘতম ম্যাচ।
মিহাই ড্যানিলা

1
আমি যদি পথ থেকে শেষ উপাদানটি পেতে চাই, তবে আমি কীভাবে এটি ব্যবহার করব? echo ${pwd##*/}কাজ করে না.
পুতনিক

2
@ পুটনিক এই আদেশটি pwdএকটি চলক হিসাবে দেখেছে । ব্যবহার করে দেখুন dir=$(pwd); echo ${dir##*/}। আমার জন্য কাজ কর!
স্ট্যান স্ট্রাম

344

আরেকটি উপায় হ'ল আগে এবং পরে বিপরীত হওয়া cut:

$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef

এটি শেষ কিন্তু এক ক্ষেত্র, বা শেষে থেকে ক্ষেত্রের যে কোনও ব্যাপ্তি পেতে খুব সহজ করে তোলে।


17
এই উত্তরটি দুর্দান্ত কারণ এটি 'কাটা' ব্যবহার করে, যা লেখক (সম্ভবত) ইতিমধ্যে পরিচিত। এছাড়াও, আমি এই উত্তরটি পছন্দ করি কারণ আমি 'কাটা' ব্যবহার করছি এবং এই সঠিক প্রশ্নটি ছিল, তাই অনুসন্ধানের মাধ্যমে এই থ্রেডটি খুঁজেছি।
ড্যানিড

6
কিছু লোককে কাটা-পেস্টের জন্য echo "1 2 3 4" | rev | cut -d " " -f1 | rev
পশুর দালান

2
রেভ | কাট-ডি-এফ 1 | রেভ এত চালাক! ধন্যবাদ! আমাকে একগুচ্ছ সাহায্য করেছে (আমার ব্যবহারের
কেসটি পুনরায়

1
আমি সবসময় ভুলে যাই rev, আমার যা প্রয়োজন তা ছিল! cut -b20- | rev | cut -b10- | rev
shearn89

আমি এই সমাধানটি দিয়ে শেষ করেছি, আমার চেষ্টা "ওআরএক-এফ" / "'{প্রিন্ট $ এনএফ}'" দিয়ে ফাইলের পথগুলি কেটে দিয়েছে, কারণ সাদা স্পেসসহ ফাইলের নামও আলাদা হয়ে যায়
THX

76

কাটাটি ব্যবহার করে শেষ ক্ষেত্রটি পাওয়া কঠিন, তবে বিশ্রী এবং পার্লের কয়েকটি সমাধান এখানে

echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'

5
গৃহীত উত্তরের চেয়ে এই সমাধানটির দুর্দান্ত সুবিধা: এটি এমন পাথগুলির সাথেও মেলে যা একটি সমাপ্তি /চরিত্র ধারণ করে বা না করে : /a/b/c/dএবং প্রক্রিয়া /a/b/c/d/করার সময় একই ফলাফল দেয় ( d) pwd | awk -F/ '{print $NF}'। গৃহীত উত্তরের ফলাফলের ক্ষেত্রে খালি ফলাফল হয়/a/b/c/d/

জিএনইউ ব্যাশ-এ অ্যাডাব্লুকে সমাধানের ক্ষেত্রে @ সেকেন্ডস, সংস্করণ ৪.৩.৪8 (১) -আর দয়া করে এটি সত্য নয়, যখনই আপনার পিছনে স্ল্যাশ পড়েছে বা না হয় তা গুরুত্বপূর্ণ matters কেবলমাত্র এডাব্লুকে /ডিলিমিটার হিসাবে ব্যবহার করবে এবং যদি আপনার পথটি হয় তবে /my/path/dir/এটি সর্বশেষ ডিলিমিটারের পরে মানটি ব্যবহার করবে, যা কেবল একটি খালি স্ট্রিং। সুতরাং আপনার যদি আমার মতো এমন কাজ করার দরকার হয় তবে স্ল্যাশ অনুসরণ করা এড়ানো ভাল।
স্ট্যামস্টার

আমি কীভাবে শেষ ক্ষেত্রটি UNTIL এ স্ট্রিং পাব?
ব্ল্যাকজ্যাক্স

1
@ ব্ল্যাকজ্যাক্স কিছু বিড়ম্বনা রয়েছে, তবে awk '{$NF=""; print $0}' FS=: OFS=:প্রায়শই এর মতো কিছু ভালভাবে কাজ করে।
উইলিয়াম পার্সেল

29

মোটামুটি সহজ ব্যবহার ধরে নিচ্ছেন (উদাহরণস্বরূপ ডিলিমিটারের নিস্তার নেই), আপনি গ্রেপ ব্যবহার করতে পারেন:

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5

ভাঙ্গন - লাইন (the) এর শেষে ডিলিমিটার ([^:]) না হয়ে সমস্ত অক্ষর সন্ধান করুন। -ও কেবল ম্যাচের অংশটি মুদ্রণ করে।


-E মানে বর্ধিত বাক্য গঠন; [^ ...] এর অর্থ তালিকাভুক্ত চর (গুলি) ব্যতীত অন্য কিছু; + এক বা একাধিক হিট (প্যাটার্নটির সর্বাধিক সম্ভাব্য দৈর্ঘ্য নেবে; এই আইটেমটি gnu এক্সটেনশন) - উদাহরণস্বরূপ পৃথককারী চর (গুলি) কোলন।
আলেকজান্ডার স্টোহর

18

একমুখী:

var1="1:2:3:4:5"
var2=${var1##*:}

আরেকটি, একটি অ্যারে ব্যবহার করে:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}

অ্যারে সহ আরও একটি:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}

বাশ (সংস্করণ> = 3.2) নিয়মিত এক্সপ্রেশন ব্যবহার করে:

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}

11
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

ডিলিমিটারটিকে কেবল একটি নতুন লাইনে অনুবাদ করুন এবং এর সাথে শেষ প্রবেশটি চয়ন করুন tail -1


এটি ব্যর্থ হবে যদি শেষ আইটেমটিতে একটি থাকে \nতবে বেশিরভাগ ক্ষেত্রে সর্বাধিক পঠনযোগ্য সমাধান।
ইয়াজো

7

ব্যবহার sed:

$ echo '1:2:3:4:5' | sed 's/.*://' # => 5

$ echo '' | sed 's/.*://' # => (empty)

$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c

$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c

4

যদি আপনার শেষ ক্ষেত্রটি একক অক্ষর হয় তবে আপনি এটি করতে পারেন:

a="1:2:3:4:5"

echo ${a: -1}
echo ${a:(-1)}

বাশে স্ট্রিং ম্যানিপুলেশন পরীক্ষা করুন ।


এই কাজ করে না: এটা গত দেয় চরিত্র এর aশেষ, না ক্ষেত্র
gniourf_gniourf

1
সত্য, এটি ধারণা, যদি আপনি শেষ ক্ষেত্রের দৈর্ঘ্যটি জানেন তবে এটি ভাল। না হলে আপনাকে অন্য কিছু ব্যবহার করতে হবে ...
আব ইরাতো

4

এখানে অনেক ভাল উত্তর আছে, কিন্তু তবুও আমি বেসনামটি ব্যবহার করে এটি ভাগ করতে চাই :

 basename $(echo "a:b:c:d:e" | tr ':' '/')

তবে আপনার স্ট্রিংয়ে ইতিমধ্যে কিছু '/' থাকলে তা ব্যর্থ হবে । যদি স্ল্যাশ / যদি আপনার ডিলিমিটার হয় তবে আপনাকে কেবল বেসনামটি ব্যবহার করতে হবে (এবং হওয়া উচিত)।

এটি সেরা উত্তর নয় তবে এটি কেবল দেখায় যে আপনি কীভাবে আদেশ আদেশ ব্যবহার করে সৃজনশীল হতে পারেন।


2

ব্যাশ ব্যবহার

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \$${#}
0

echo ${!#}পরিবর্তে ব্যবহার করতে পারে eval echo \$${#}
রাফা

2
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

প্রথমে xargs এটিকে ":" ব্যবহার করে বিভক্ত করুন - এন 1 এর অর্থ প্রতিটি লাইনের কেবল একটি অংশ থাকে T তারপরে, শেষ অংশটি ছাঁটাই করুন।


1
for x in `echo $str | tr ";" "\n"`; do echo $x; done

2
যে কোনও ক্ষেত্রে যদি সাদা জায়গা থাকে তবে এটি সমস্যার মধ্যে পড়ে। এছাড়াও, এটি সর্বশেষ ক্ষেত্রটি পুনরুদ্ধার প্রশ্নে সরাসরি সম্বোধন করে না ।
চিপনার

1

পাইথনের সাথে যারা স্বাচ্ছন্দ্য বোধ করেন তাদের জন্য https://github.com/Russell91/pythonpy এই সমস্যাটি সমাধান করার জন্য একটি দুর্দান্ত পছন্দ।

$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'

Pythonpy সাহায্যের থেকে: -x treat each row of stdin as x

এই সরঞ্জামটির সাহায্যে পাইথন কোডটি লেখা সহজ যা ইনপুটটিতে প্রয়োগ হয়।


1

উত্তর সহ কিছুটা দেরি হতে পারে যদিও একটি সহজ সমাধান হ'ল ইনপুট স্ট্রিংয়ের ক্রমটিকে বিপরীত করা। এটি আপনাকে সর্বদা শেষ আইটেমটি দৈর্ঘ্য নির্বিশেষে অর্জন করার অনুমতি দেবে।

[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5

তবে এটি লক্ষণীয় গুরুত্বপূর্ণ, যদি এই পদ্ধতিটি ব্যবহার করে এবং সংখ্যাগুলি 1 ডিজিটের চেয়ে বড় হয় (বা কোনও পরিস্থিতিতে এক বর্ণের চেয়ে বড়), আপনাকে পাইপযুক্ত আউটপুটটির উপরে আরেকটি 'রেভ' কমান্ড চালাতে হবে।

[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24

আশা করি আমি সাহায্য করতে পারি, চিয়ার্স


1

পঠিত বিল্টিন ব্যবহার করে একটি সমাধান:

IFS=':' read -a fields <<< "1:2:3:4:5"
echo "${fields[4]}"

বা, এটি আরও জেনেরিক করতে:

echo "${fields[-1]}" # prints the last item

0

আপনি যদি পাইথন পছন্দ করেন এবং প্যাকেজ ইনস্টল করার বিকল্প রাখেন তবে আপনি পাইথন ইউটিলিটিটি ব্যবহার করতে পারেন ।

# install pythonp
pythonp -m pip install pythonp

echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5

অজগর সরাসরি এটি করতে পারে: echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
মর্টেনবি

@ মর্টেনবি আপনি ভুল করেছেন pythonpপ্যাকেজের পুরো উদ্দেশ্যটি python -cহ'ল কম চরিত্রের টাইপের মতো একই কাজগুলি করা। সংগ্রহস্থলটিতে README দেখুন দয়া করে।
বোমা

0

রেজেক্সের মিলটি sedলোভী (সর্বদা সর্বশেষ ইভেন্টে যায়), আপনি এখানে আপনার সুবিধার্থে ব্যবহার করতে পারেন:

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.