ব্যাশে কমান্ডের আউটপুটটির প্রথম শব্দটি কীভাবে পুনরুদ্ধার করবেন?


126

আমি উদাহরণস্বরূপ ভালো দখল আছে: echo "word1 word2"। আমি একটি পাইপ লাগাতে চাই ( |) এবং কমান্ড থেকে ওয়ার্ড 1 পেতে পারি।

echo "word1 word2" | ....

পাইপের পরে কী রাখব জানি না।

উত্তর:


201

হোয়াইটস্পেসের জন্য যদি আপনাকে পশ্চাদপসরণের মুখোমুখি হতে হয় তবে অজ হ'ল একটি ভাল বিকল্প কারণ এটি এটি আপনার যত্ন নেবে:

echo "   word1  word2 " | awk '{print $1;}' # Prints "word1"

কাট যদিও এটি যত্ন নেবে না:

echo "  word1  word2 " | cut -f 1 -d " " # Prints nothing/whitespace

এখানে 'কাটা' কোনও কিছুই / সাদা স্থান মুদ্রণ করে না, কারণ কোনও জায়গার আগে প্রথম জিনিসটি ছিল আরেকটি স্থান।


আধা-কোলন প্রয়োজনীয়?
অ্যালিস পুরসেল

1
এটি "শীর্ষস্থানীয়" হোয়াইটস্পেস (স্ট্রিংয়ের শুরুতে) হওয়া উচিত, "ট্রেলিং" নয়।
ব্যবহারকারী 202729

অ্যালিস্পুরসেল আমি এটি ব্যবহার করেই চেষ্টা করেছি; এবং এটি আমার পক্ষে কাজ করেছে (এমবিপি 10.14.2)
স্যামি বেঞ্চিরিফ

1
স্ট্রিংটি উদাহরণস্বরূপ "ফার্স্ট ওয়ার্ড, সেকেন্ড ওয়ার্ড" হিসাবে যদি এটি কাজ করে না যে স্থান দ্বারা স্থানান্তরিত কমান্ড হিসাবে ডিলিটর থাকে
রজার ওবা

@ রোজারবা এটি ওপি-র প্রশ্ন ছিল না, তবে আপনি -F","কমা দিয়ে ডিফল্ট ক্ষেত্র বিভাজক (একটি স্থান) ওভাররাইড করতে পারেন ।
pjd

70

বাহ্যিক কমান্ড ব্যবহার করার দরকার নেই। বাশ নিজেই কাজটি করতে পারে। "ওয়ার্ড 1 ওয়ার্ড 2" ধরে ধরে আপনি কোথাও থেকে এসেছেন এবং ভেরিয়েবলে সংরক্ষণ করেছেন, যেমন

$ string="word1 word2"
$ set -- $string
$ echo $1
word1
$ echo $2
word2

আপনি যদি চান তবে এখন আপনি অন্য ভেরিয়েবলের জন্য $ 1, বা $ 2 ইত্যাদি নির্ধারণ করতে পারেন।


11
শুধুমাত্র শেল বিল্ট-ইনগুলি ব্যবহার করার জন্য এবং +1 stdin। @ ম্যাট এম এর --অর্থ হল stdin, তাই $stringহিসাবে পাস করা হচ্ছে stdinstdinআর্গুমেন্ট মধ্যে হোয়াইটস্পেস বিভাজিত হয় $1, $2, $3, ইত্যাদি - শুধু একটি ব্যাশ প্রোগ্রাম মূল্যায়ন আর্গুমেন্ট (যেমন চেক মত $1, $2ইত্যাদি), এই পদ্ধতির সুবিধা শেল এর প্রবণতা বিভক্ত লাগে stdinআর্গুমেন্ট মধ্যে স্বয়ংক্রিয়ভাবে সরানোর প্রয়োজনে awkবা cut
কালেব জু

3
@ কালেবক্সু স্টিডিন নয়, setশেল আর্গুমেন্ট সেট করে।
গুইডো

9
word1=$(IFS=" " ; set -- $string ; echo $1)শব্দের মধ্যে স্থানটি সঠিকভাবে সনাক্ত করতে আইএফএস সেট করুন। He 1 এর মূল বিষয়বস্তু আঁকড়ে না এড়াতে বন্ধনীগুলিতে মোড়ানো।
স্টিভ পিচারস

পথের নাম সম্প্রসারণের সাপেক্ষে এটি ভাঙ্গা। এটি দিয়ে চেষ্টা করুন string="*"। আশ্চর্য.
gniourf_gniourf

32

আমি মনে করি একটি কার্যকর উপায় হ'ল বাশ অ্যারে ব্যবহার:

array=( $string ) # do not use quotes in order to allow word expansion
echo ${array[0]}  # You can retrieve any word. Index runs from 0 to length-1

এছাড়াও, আপনি সরাসরি পাইপ-লাইনে অ্যারে পড়তে পারেন:

echo "word1 word2" | while read -a array; do echo "${array[0]}" ; done

1
echo " word1 word2 " | { read -a array ; echo ${array[0]} ; }
Boontawee হোম

পথের নাম সম্প্রসারণের সাপেক্ষে এটি ভাঙ্গা। এটি দিয়ে চেষ্টা করুন string="*"। আশ্চর্য.
gniourf_gniourf

whileপ্রতিটি লাইনে প্রতিটি প্রথম শব্দ পুনরুদ্ধার করতে সিনট্যাক্সটি ব্যবহার করুন । অন্যথায়, Boontawee হোম পদ্ধতির ব্যবহার করুন। এছাড়াও, দয়া করে নোট করুন যে echo "${array[0]}"gniourf-gniourf দ্বারা যেমনটি লক্ষ্য করা গেছে তেমন বিস্তার রোধ করতে উদ্ধৃতি দেওয়া হয়েছে।
যিশাইস

আপনি যদি শঙ্কার সংখ্যার চেয়ে বড় অ্যারের সূচকটি অ্যাক্সেস করার চেষ্টা করেন তবে আপনি ত্রুটি পাবেন না। আপনি খালি লাইন পাবেন
ধুমিল আগরওয়াল

26
echo "word1 word2 word3" | { read first rest ; echo $first ; }

এটির সুবিধাটি রয়েছে যা বাহ্যিক কমান্ড ব্যবহার করছে না এবং $ 1, $ 2 ইত্যাদি পরিবর্তনশীল অক্ষত।


$1, $2, …স্ক্রিপ্ট রচনার জন্য ভেরিয়েবল অক্ষত রেখে দেওয়া একটি অত্যন্ত কার্যকর বৈশিষ্ট্য!
সার্জ Stroobandt

14

যদি আপনি নিশ্চিত হন যে কোনও শীর্ষস্থানীয় স্থান নেই, আপনি ব্যাশ প্যারামিটার বিকল্প ব্যবহার করতে পারেন:

$ string="word1  word2"
$ echo ${string/%\ */}
word1

একক স্থান থেকে পালানোর জন্য সতর্কতা অবলম্বন করুন। প্রতিস্থাপনের নিদর্শনগুলির আরও উদাহরণের জন্য এখানে দেখুন । আপনার যদি বাশ> 3.0.০ থাকে তবে আপনি নেতৃস্থানীয় স্পেসগুলি মোকাবেলায় নিয়মিত প্রকাশের মিলও ব্যবহার করতে পারেন - এখানে দেখুন :

$ string="  word1   word2"
$ [[ ${string} =~ \ *([^\ ]*) ]]
$ echo ${BASH_REMATCH[1]}
word1

11

আপনি অজানা চেষ্টা করতে পারেন

echo "word1 word2" | awk '{ print $1 }'

জাঙ্কের সাহায্যে আপনার পছন্দ মতো কোনও শব্দ বাছাই করা সত্যিই সহজ ($ 1, $ 2, ...)


11

শেল প্যারামিটার সম্প্রসারণ ব্যবহার করে %% *

শেল প্যারামিটার সম্প্রসারণ ব্যবহার করে এখানে আরও একটি সমাধান দেওয়া হয়েছে । এটি প্রথম শব্দের পরে একাধিক স্পেসের যত্ন নেয়। প্রথম শব্দের সামনে স্পেস পরিচালনা করার জন্য আরও একটি অতিরিক্ত প্রসারণ প্রয়োজন।

string='word1    word2'
echo ${string%% *}
word1

string='word1    word2      '
echo ${string%% *}
word1

ব্যাখ্যা

%%প্রকাশ করে মুছে ফেলার দীর্ঘতম সম্ভব ম্যাচ  *(a স্থান যাই হোক না কেন অন্য অক্ষর যে কোন সংখ্যার থাকে) চিহ্ন অংশ string


9

আমি ভাবলাম যে শীর্ষের বেশ কয়েকটি উত্তর গতির ক্ষেত্রে কীভাবে পরিমাপ করেছে। আমি নিম্নলিখিতটি পরীক্ষা করেছি:

1 @ ম্যাটটিভ এর

echo "..." | awk '{print $1;}'

2 @ ঘোস্টডোগ 74 এর

string="..."; set -- $string; echo $1

3 @ বুন্টাওয়ে-হোম

echo "..." | { read -a array ; echo ${array[0]} ; }

এবং 4 @ বুন্টাওয়ে-হোমস

echo "..." | { read first _ ; echo $first ; }

আমি 215 5-অক্ষরের শব্দের সাথে একটি পরীক্ষার স্ট্রিং ব্যবহার করে ম্যাকোস-এর একটি জেডএস টার্মিনালে বাশ স্ক্রিপ্টে পাইথনের টাইমিট দিয়ে তাদের পরিমাপ করেছি। প্রতিটি পরিমাপ পাঁচবার হয়েছে (ফলাফলগুলি ছিল 100 লুপের জন্য, 3 টির মধ্যে সেরা) এবং ফলাফলগুলি গড়:

method       time
--------------------------------
1. awk       9.2ms
2. set       11.6ms (1.26 * "1")
3. read -a   11.7ms (1.27 * "1")
4. read      13.6ms (1.48 * "1")

চমৎকার কাজ, ভোটাররা 👏 ভোট (এই লেখার মতো) সমাধানগুলির গতির সাথে মেলে!


অদ্ভুত যে আপনি 3 টি ড্যাশ পরিমাপ করতে পারবেন, যেহেতু ড্যাশ অ্যারেগুলিকে সমর্থন করে না ( read -aড্যাশটিতে অবৈধ)।
gniourf_gniourf

হ্যাঁ এটা অদ্ভুত। আমি এটিকে বাতিল করে দিয়েছি, গতি পরীক্ষা করেছিলাম, তারপরে "আমি কেন সেটিকে ছাড়বো" ভেবেছিলাম এবং এটিকে যুক্ত করে দিয়েছি Rem এখনই এটি সরানো হচ্ছে, এবং আমার কিছু ভুল না হয়েছে তা নিশ্চিত করার জন্য আমি পরে বিষয়গুলি পুনরায় চালু করতে পারি
হেনরি

6
echo "word1 word2" | cut -f 1 -d " "

কাটা স্ট্রিং "" (-d "") দ্বারা সীমানাঙ্কিত ক্ষেত্রগুলির তালিকা থেকে প্রথম ক্ষেত্রের (-f 1) কেটে দেয়


এটি একটি উপায়, তবে আপনার কাটা স্টেটমেন্ট শব্দের মধ্যে একাধিক স্পেস আলাদা করতে পারবে না যদি সে পরে শব্দটি 2 পেতে চায়
ghostdog74

হ্যাঁ, অ্যাজক সমাধানটি আরও ভাল।
লাজেতে

3

read তোমার বন্ধু:

  • স্ট্রিং যদি কোনও ভেরিয়েবলে থাকে:

    string="word1 word2"
    read -r first _ <<< "$string"
    printf '%s\n' "$first"
  • আপনি যদি পাইপে কাজ করছেন: প্রথম ক্ষেত্রে: আপনি কেবল প্রথম লাইনের প্রথম শব্দটি চান:

    printf '%s\n' "word1 word2" "line2" | { read -r first _; printf '%s\n' "$first"; }

    দ্বিতীয় কেস: আপনি প্রতিটি লাইনের প্রথম শব্দটি চান:

    printf '%s\n' "word1 word2" "worda wordb" | while read -r first _; do printf '%s\n' "$first"; done

শীর্ষস্থানীয় স্থান থাকলে এই কাজগুলি:

printf '%s\n' "   word1 word2" | { read -r first _; printf '%s\n' "$first"; }

0

যেহেতু পার্ল আওকের কার্যকারিতা অন্তর্ভুক্ত করে এটি পার্ল দিয়েও সমাধান করা যেতে পারে:

echo " word1 word2" | perl -lane 'print $F[0]'

0

আমি একটি এমবেডেড ডিভাইস নিয়ে কাজ করছিলাম যার পার্ল, অ্যাজক বা পাইথন ছিল না এবং পরিবর্তে সেড দিয়ে এটি করেছি। এটি প্রথম শব্দের আগে একাধিক স্পেস সমর্থন করে (যা cutএবং bashসমাধানগুলি পরিচালনা করে না)।

VARIABLE="  first_word_with_spaces_before_and_after  another_word  "
echo $VARIABLE | sed 's/ *\([^ ]*\).*/\1/'

psপ্রক্রিয়া আইডির জন্য গ্রেপিংয়ের সময় এটি খুব কার্যকর ছিল যেহেতু কেবলমাত্র ব্যাশ ব্যবহার করে এখানে অন্যান্য সমাধানগুলি psসারিবদ্ধ করার জন্য ব্যবহৃত প্রথম স্থান সরাতে সক্ষম হয় নি ।

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