বাশ ভেরিয়েবল থেকে হোয়াইটস্পেস কীভাবে ট্রিম করবেন?


920

এই কোড সহ আমার কাছে একটি শেল স্ক্রিপ্ট রয়েছে:

var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

তবে শর্তসাপেক্ষ কোডটি সর্বদা কার্যকর করে, কারণ hg stসর্বদা কমপক্ষে একটি নিউলাইন চরিত্র প্রিন্ট করে।

  • সেখান থেকে হোয়াইটস্পেস স্ট্রিপ একটি সহজ উপায় আছে কি $var(যেমন trim()মধ্যে পিএইচপি )?

অথবা

  • এই সমস্যাটি মোকাবেলার জন্য কি কোনও স্ট্যান্ডার্ড উপায় আছে?

আমি সেড বা এডাব্লুকে ব্যবহার করতে পারি , তবে আমি ভাবতে চাই যে এই সমস্যার আরও সুন্দর সমাধান আছে।


3
সম্পর্কিত, আপনি যদি কোনও পূর্ণসংখ্যার উপর স্থানটি ছাঁটাই করতে চান এবং কেবল পূর্ণসংখ্যা পেতে চান তবে $ (($ var)) দিয়ে মুড়িয়ে ফেলুন এবং ডাবল কোটের অভ্যন্তরেও এটি করতে পারেন। আমি গুরুত্বপূর্ণ হয়ে উঠি যখন আমি তারিখের বিবৃতি এবং ফাইলের নাম ব্যবহার করি।
ভলমাইক

"এই সমস্যাটি মোকাবিলার কোনও মানক উপায় আছে কি?" হ্যাঁ, [[এর পরিবর্তে [ব্যবহার করুন]। $ var=$(echo) $ [ -n $var ]; echo $? #undesired test return 0 $ [[ -n $var ]]; echo $? 1
user.friendly

এটি যদি সহায়তা করে তবে কমপক্ষে উবুন্টু 16.04 এ এটি পরীক্ষা করে নিচ্ছি। ব্যবহার করে নিম্নলিখিত ম্যাচ প্রতি উপায় ছাঁটা: echo " This is a string of char " | xargs। আপনি কিন্তু টেক্সট একটি একক উদ্ধৃতি থাকে, তাহলে আপনি নিম্নলিখিতগুলি করতে পারেন: echo " This i's a string of char " | xargs -0। নোট করুন যে আমি সর্বশেষে xargs উল্লেখ করেছি (4.6.0)
লুইস আলভারাডো

ব্যাকটিকস শেষ নিউলাইনটি গ্রাস করায় কোনও নিউলাইনের কারণে শর্তটি সত্য নয়। এটি কিছুই মুদ্রণ করবে না test=`echo`; if [ -n "$test" ]; then echo "Not empty"; fi, তবে এটি হবে test=`echo "a"`; if [ -n "$test" ]; then echo "Not empty"; fi- সুতরাং শেষে কেবল একটি নতুন লাইন ছাড়াও আরও কিছু থাকতে হবে।
মক্কি

এ = "123 4 5 6"; খ = echo $A | sed -r 's/( )+//g';
বুড়িউজ

উত্তর:


1021

শীর্ষস্থানীয়, চলমান এবং মধ্যবর্তী হোয়াইটস্পেস যুক্ত একটি ভেরিয়েবল সংজ্ঞা দিন:

FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16

কিভাবে সব হোয়াইটস্পেস (দ্বারা প্রকাশ মুছে ফেলার জন্য [:space:]tr):

FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12

কেবল শীর্ষস্থানীয় হোয়াইটস্পেস কীভাবে সরাবেন:

FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15

কেবল পেছনের সাদা স্থান কীভাবে সরিয়ে ফেলা যায়:

FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15

নেতৃস্থানীয় এবং অনুসরণযোগ্য স্থানগুলি কীভাবে সরিয়ে ফেলতে হবে - শৃঙ্খলাবদ্ধ sed:

FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14

অথবা, আপনার ব্যাশ এটিকে সমর্থন করে তাহলে, আপনি প্রতিস্থাপন করতে পারেন echo -e "${FOO}" | sed ...সঙ্গে sed ... <<<${FOO}, তাই মত (হোয়াইটস্পেস trailing জন্য):

FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"

63
সমস্ত ধরণের সাদা স্থান পরিচালনা করার জন্য সমাধানটি সাধারণ করতে , স্থান অক্ষরটি প্রতিস্থাপন করুন trএবং এর সাথে sedকমান্ড দিন [[:space:]]। নোট করুন যে sedপদ্ধতিটি কেবল একক-লাইন ইনপুটটিতে কাজ করবে । যে মাল্টি-লাইন ইনপুট নিয়ে কাজ করে এবং বাশের অন্তর্নির্মিত বৈশিষ্ট্যগুলি ব্যবহার করে এমন পদ্ধতির জন্য, @ বাশফু এবং @ গুরুম এর উত্তরগুলি দেখুন। @ নিকোলাস সুকিনের সমাধানটির একটি সাধারণীকরণ, ইনলাইন সংস্করণটি দেখতে দেখতে এটির মত trimmed=$([[ " test test test " =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]; echo -n "${BASH_REMATCH[1]}")
লাগবে

7
আপনি যদি এটি প্রায়শই alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"করেন তবে আপনার সংযোজন ~/.profileআপনাকে ব্যবহার করতে দেয় echo $SOMEVAR | trimএবং cat somefile | trim
উদাহরণস্বরূপ 15

আমি লিখেছেন sedসমাধান মাত্র দুটি বদলে একটি একক অভিব্যক্তি ব্যবহার করে: sed -r 's/^\s*(\S+(\s+\S+)*)\s*$/\1/'। এটি শীর্ষস্থানীয় এবং পূর্ববর্তী হোয়াইটস্পেসকে ছাঁটাই করে এবং মাঝখানে সাদা-স্থানের অক্ষরগুলির কোনও হোয়াইটস্পেস-বিচ্ছিন্ন ক্রমগুলি ক্যাপচার করে। উপভোগ করুন!
ভিক্টর জামামানিয়ান

ইনপুটটিতে কেবল শ্বেতস্থান থাকলে আপনার সমাধানটি কার্যকর না করে ict ম্যাটিভি এবং উদাহরণস্বরূপ প্রদত্ত দ্বি-প্যাটার্ন সেড সমাধানগুলি কেবলমাত্র সাদা বাক্সে ইনপুট দিয়ে কাজ করে work
টোরবেন

@ টরবেন ফেয়ার পয়েন্ট আমি মনে করি একক প্রকাশটি শর্তসাপেক্ষে তৈরি করা যেতে পারে |, যাতে এটি বেশ কয়েকটির পরিবর্তে একক প্রকাশ হিসাবে রাখা যায়।
ভিক্টর জামামানিয়ান

964

একটি সহজ উত্তর:

echo "   lol  " | xargs

জার্গস আপনার জন্য ছাঁটাই করবে। এটি একটি কমান্ড / প্রোগ্রাম, কোনও প্যারামিটার নয়, ছাঁটা স্ট্রিংটি ফেরত দেয়, এটি সহজ

দ্রষ্টব্য: এটি সমস্ত অভ্যন্তরীণ স্থানগুলি সরিয়ে দেয় না তাই "foo bar"একই থাকে; এটা হয়ে যায় না "foobar"। তবে একাধিক স্পেস একক স্পেসে ঘনীভূত "foo bar"হবে , তাই হয়ে যাবে "foo bar"। তদতিরিক্ত এটি লাইন অক্ষরের শেষ সরিয়ে দেয় না।


27
খুশী হলাম। এটি সত্যিই ভাল কাজ করে। আমি xargs echoযা করছি তা কেবল ভারবস হয়ে যাওয়ার জন্য আমি এটিটি পাইপ করার সিদ্ধান্ত নিয়েছি , তবে এটির নিজস্ব xargs ডিফল্টরূপে প্রতিধ্বনি ব্যবহার করবে।
উইল

24
দুর্দান্ত কৌশল, তবে সাবধান থাকুন, আপনি এটি এক-লাইনের স্ট্রিংয়ের জন্য ব্যবহার করতে পারেন তবে xargs ডিজাইনের মাধ্যমে - এটি কেবলমাত্র বহু-লাইন পাইপযুক্ত সামগ্রী দিয়ে ট্রিমিং করবে না। সেড আপনার বন্ধু তখন।
জোসলিন ডেলাল্যান্ডে

22
এক্সার্গসের সমস্যাটি হ'ল এটি একটি নতুন লাইন প্রবর্তন করবে, আপনি যদি নতুন লাইনটি বন্ধ রাখতে চান তবে আমি sed 's/ *$//'বিকল্প হিসাবে প্রস্তাব দেব recommend আপনি দেখতে পারেন xargsভালো সম্পর্কে newline: echo -n "hey thiss " | xargs | hexdump আপনি লক্ষ্য করবেন সম্পর্কে newline হয়। আপনি যদি এর সাথে একই করেন : আপনি দেখতে পাবেন , কোনও নতুন লাইন নেই। 0a73asedecho -n "hey thiss " | sed 's/ *$//' | hexdump0073

8
সাবধান হন; স্ট্রিং থেকে xargs এর মধ্যে অতিরিক্ত উদ্বৃত্ত স্থান থাকলে এটি শক্ত হয়ে যাবে। "এটি একটি যুক্তি" এর মতো। xargs চারটি মধ্যে বিভক্ত হবে।
bos

64
এইটা খারাপ. 1. এটি পরিণত a<space><space>bহবে a<space>b। 2. আরও বেশি: এটি রূপান্তরিত a"b"c'd'eহবে abcde। 3. আরো অনেক কিছু: এটা ব্যর্থ হবে a"b, ইত্যাদি
বিদেশে

357

একটি সমাধান রয়েছে যা কেবল বাশ অন্তর্নির্মিতগুলিকে ওয়াইল্ডকার্ডস ব্যবহার করে :

var="    abc    "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"   
printf '%s' "===$var==="

এখানে একটি ফাংশন একই আবৃত:

trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"   
    printf '%s' "$var"
}

আপনি উদ্ধৃত আকারে ছাঁটাই করতে স্ট্রিংটি পাস করুন। উদাহরণ:

trim "   abc   "

এই সমাধান সম্পর্কে একটি দুর্দান্ত বিষয় হ'ল এটি কোনও পসিক্স-কমপ্লায়েন্ট শেলের সাথে কাজ করবে।

উল্লেখ


17
চতুর! এটি আমার প্রিয় সমাধান কারণ এটি অন্তর্নির্মিত ব্যাশ কার্যকারিতাটি ব্যবহার করে। পোস্ট করার জন্য ধন্যবাদ! @ সান, এটি দুটি নেস্টেড স্ট্রিং ট্রিমস। উদাহরণস্বরূপ, s=" 1 2 3 "; echo \""${s%1 2 3 }"\"শেষ থেকে সবকিছু ছাঁটাই করা হবে, নেতৃস্থানীয় ফিরে " "। এটিকে বজায় 1 2 3 রেখে [![:space:]]*এটিকে "প্রথম প্রথম অ-স্থানের চরিত্রটি খুঁজে বের করুন, তারপরে এটি এবং তার পরে সবকিছু" ক্লোবার করুন to %%পরিবর্তে ব্যবহার করা %ছাঁটাই থেকে শেষ অপারেশন লোভী করে তোলে। এটি অ-লোভী ছাঁটাই-শুরু থেকে বাসা বেঁধেছে তাই কার্যকরভাবে, আপনি " "শুরু থেকেই ছাঁটা । তারপরে, শেষ স্থানগুলির জন্য%, #, এবং * অদলবদল করুন। বাম!
মার্ক জি।

2
আমি কোনও অযাচিত পার্শ্ব প্রতিক্রিয়া খুঁজে পাইনি এবং মূল কোডটি অন্য পসিক্স-এর মতো শেলগুলির সাথেও কাজ করে। তবে সোলারিস 10 এর অধীনে এটি কাজ করে না /bin/sh(কেবল এটির সাথে /usr/xpg4/bin/sh, তবে এটি সাধারণত শ স্ক্রিপ্টগুলির সাথে ব্যবহৃত হবে না)।
ভিঙ্ক 17

9
সেড, টিআর ইত্যাদি ব্যবহারের চেয়ে অনেক ভাল সমাধান, যেহেতু এটি কোনও দ্রুত কাঁটাচামচ () এড়িয়ে চলা দ্রুত। গতিতে সাইগউইন পার্থক্য হ'ল দৈর্ঘ্যের অর্ডার।
জিন পাভলভস্কি

9
@ সান প্রথমে আমি স্ট্যাম্প হয়ে গিয়েছিলাম কারণ আমি ভেবেছিলাম এগুলি নিয়মিত প্রকাশ। তারা না. পরিবর্তে, এটি প্যাটার্ন ম্যাচিং সিনট্যাক্স ( gnu.org/software/bash/manual/html_node/Pattern-Matching.html , wiki.bash-hackers.org/syntax/ Pattern ) সাবস্ট্রিং অপসারণে ব্যবহৃত হয় ( tldp.org/LDP/abs /html/string-manipulation.html )। তাই ${var%%[![:space:]]*}বলেছে " varএর দীর্ঘতম সাবস্ট্রিং থেকে অপসারণ যা কোনও স্থান ছাড়াই অক্ষর দিয়ে শুরু হয়"। তার অর্থ আপনি কেবলমাত্র শীর্ষস্থানীয় স্থান (গুলি) এর সাথে বাকী রয়েছেন যা আপনি পরবর্তীকালে সরিয়ে ফেলুন ${var#..। নিম্নলিখিত লাইনটি (অনুসরণ করা) বিপরীত।
ওহাদ স্নাইডার

8
এটি অপ্রতিরোধ্যভাবে আদর্শ সমাধান। এক বা একাধিক বহিরাগত প্রসেস forking (যেমন, awk, sed, tr, xargs) একটা একক পংক্তি থেকে ট্রিম হোয়াইটস্পেস করতে নিছক মৌলিকভাবে উন্মাদ হয় - বিশেষ করে যখন সবচেয়ে শাঁস (ব্যাশ সহ) ইতিমধ্যে দেশীয় স্ট্রিং সুবিধা munging আউট-অফ-বক্স প্রদান।
সিসিল কারি

80

বাশের একটি প্যারামিটার সম্প্রসারণ নামে একটি বৈশিষ্ট্য রয়েছে যা অন্যান্য বিষয়ের মধ্যে তথাকথিত নিদর্শনগুলির উপর ভিত্তি করে স্ট্রিং প্রতিস্থাপনের অনুমতি দেয় (নিদর্শনগুলি নিয়মিত প্রকাশের সাথে সাদৃশ্যযুক্ত, তবে মৌলিক পার্থক্য এবং সীমাবদ্ধতা রয়েছে)। [প্রবাহের মূল লাইন: বাশের নিয়মিত প্রকাশ থাকে তবে সেগুলি খুব গোপন থাকে:]

নিম্নলিখিতটি দেখায় যে কীভাবে একটি পরিবর্তনশীল মান থেকে সমস্ত সাদা স্থান (এমনকি অভ্যন্তর থেকে) সরিয়ে ফেলা যায়।

$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef

2
বা বরং, এটি কোনও ভ্যারির মাঝখানে ফাঁকা জায়গাগুলির জন্য কাজ করে, তবে যখন আমি এটি শেষে নোঙ্গর করার চেষ্টা করি না।
পল টমবলিন 21

এটি কোন সাহায্য করে? মানচিত্রটি থেকে: "$ {পরামিতি / প্যাটার্ন / স্ট্রিং} [...] প্যাটার্নটি যদি% দিয়ে শুরু হয় তবে অবশ্যই এটি প্যারামিটারের বর্ধিত মানের শেষে মিলবে।"

@ অ্যান্ট, সুতরাং এগুলি আসলেই নিয়মিত প্রকাশ নয়, তবে এরকম কিছু?
পল টমবলিন

3
তারা রেজেেক্স, কেবল একটি অদ্ভুত উপভাষা।

13
${var/ /}প্রথম স্থানের অক্ষর সরিয়ে দেয়। ${var// /}সমস্ত স্থান অক্ষর মুছে ফেলা। কেবল এই নির্মাণের সাহায্যে কেবল শীর্ষস্থানীয় এবং পিছনের সাদা অংশ ছাঁটাই করার কোনও উপায় নেই।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

60

কোনও স্ট্রিংয়ের শুরু এবং শেষ থেকে সমস্ত ফাঁকা স্থান সরিয়ে ফেলতে (রেখার অক্ষরের শেষ সহ):

echo $variable | xargs echo -n

এটি নকল স্থানগুলিও সরিয়ে ফেলবে:

echo "  this string has a lot       of spaces " | xargs echo -n

উত্পাদন: 'এই স্ট্রিংয়ের অনেক স্পেস রয়েছে'


5
মূলত xargs স্ট্রিং থেকে সমস্ত ডিলিমিটারগুলি সরিয়ে দেয়। ডিফল্টরূপে এটি স্থানটি ডিলিমিটার হিসাবে ব্যবহার করে (এটি -d বিকল্প দ্বারা পরিবর্তিত হতে পারে)।
rkachach

4
এটি এখন পর্যন্ত সবচেয়ে পরিষ্কার (সংক্ষিপ্ত এবং পাঠযোগ্য উভয়) সমাধান।
পোথেরকা

আপনার এতো দরকার কেন echo -n? echo " my string " | xargsএকই আউটপুট আছে।
bfontaine

প্রতিধ্বনি লাইনটির
প্রান্তটিও

55

একটি নেতৃস্থানীয় এবং একটি পিছনে স্থান স্ট্রিপ

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

উদাহরণ স্বরূপ:

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

আউটপুট:

'one leading', 'one trailing', 'one leading and one trailing'

সমস্ত নেতৃস্থানীয় এবং অনুসরণযোগ্য স্থানগুলি স্ট্রিপ করুন

trim()
{
    local trimmed="$1"

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

উদাহরণ স্বরূপ:

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

আউটপুট:

'two leading', 'two trailing', 'two leading and two trailing'

9
এটি কেবল 1 স্পেস অক্ষর ছাঁটাই করবে। সুতরাং প্রতিধ্বনির ফলাফল'hello world ', 'foo bar', 'both sides '
জো

@ জো আমি আরও একটি ভাল বিকল্প যুক্ত করেছি।
wjandrea

42

গ্লোববিংয়ের উপর বাশ গাইড বিভাগ থেকে

একটি প্যারামিটার বিস্তারে এক্সটগ্লোব ব্যবহার করতে

 #Turn on extended globbing  
shopt -s extglob  
 #Trim leading and trailing whitespace from a variable  
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}  
 #Turn off extended globbing  
shopt -u extglob  

এখানে কোনও কার্যক্রমে মোড়ানো একই কার্যকারিতা এখানে রয়েছে (দ্রষ্টব্য: ফাংশনে পাস হওয়া ইনপুট স্ট্রিংটির উদ্ধৃতি দেওয়া দরকার):

trim() {
    # Determine if 'extglob' is currently on.
    local extglobWasOff=1
    shopt extglob >/dev/null && extglobWasOff=0 
    (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
    # Trim leading and trailing whitespace
    local var=$1
    var=${var##+([[:space:]])}
    var=${var%%+([[:space:]])}
    (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
    echo -n "$var"  # Output trimmed string.
}

ব্যবহার:

string="   abc def ghi  ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");  
echo "$trimmed";

যদি আমরা একটি সাব-শেলের মধ্যে সম্পাদন করতে ফাংশনটি পরিবর্তন করি তবে এক্সটগ্লোবের জন্য আমাদের বর্তমান শেল বিকল্পটি পরীক্ষা করার বিষয়ে আমাদের চিন্তা করতে হবে না, আমরা কেবল বর্তমান শেলকে প্রভাবিত না করে সেট করতে পারি। এটি দুর্দান্তভাবে ফাংশনটিকে সহজতর করে। আমি "স্থানে" অবস্থানগত পরামিতিগুলিও আপডেট করি যাতে আমার এমনকি স্থানীয় ভেরিয়েবলের প্রয়োজন হয় না

trim() {
    shopt -s extglob
    set -- "${1##+([[:space:]])}"
    printf "%s" "${1%%+([[:space:]])}" 
}

তাই:

$ s=$'\t\n \r\tfoo  '
$ shopt -u extglob
$ shopt extglob
extglob         off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo  '<
>foo<
$ shopt extglob
extglob         off

2
আপনি যেমন ছাঁটা পর্যবেক্ষণ করেছেন () কেবলমাত্র শীর্ষস্থানীয় এবং অনুসরণযোগ্য শ্বেতস্পেস সরিয়ে দেয়।
গুরুম

যেমন মেকলেমেন্ট ইতিমধ্যে উল্লেখ করেছে যে আপনাকে ফাংশন প্যারামিটারটি উদ্ধৃত স্ট্রিং হিসাবে ie (ট্রিম $ স্ট্রিং) পরিবর্তে ie (ট্রিম "$ স্ট্রিং") হিসাবে পাস করতে হবে। সঠিক ব্যবহারটি দেখানোর জন্য আমি কোডটি আপডেট করেছি। ধন্যবাদ।
গুরুএম

শেল অপশন সম্পর্কে যতটুকু আমি জানার প্রশংসা করি, আমি মনে করি না যে শেষের ফলাফলটি কেবল 2 প্যাটার্ন বিকল্পের চেয়ে বেশি মার্জিত
সেপ্টেম্বর

নোট করুন (বাশের সাম্প্রতিক পর্যায়ে যথেষ্ট সংস্করণ দিয়ে?), আপনি বিকল্পটি পুনরুদ্ধারের প্রক্রিয়াটি সহজতর করতে পারেন extglob, এটি ব্যবহার করে shopt -p: কেবল local restore="$(shopt -p extglob)" ; shopt -s extglobআপনার ফাংশনের শুরুতে এবং eval "$restore"শেষে (কেবল মঞ্জুর করা ছাড়া, অ্যাভালটি মন্দ!) লিখুন।
Maëlan

দুর্দান্ত সমাধান! একটি সম্ভাব্য উন্নতি: দেখে মনে হচ্ছে এটি [[:space:]]ভাল, একটি স্থান: ${var##+( )}এবং ${var%%+( )}পাশাপাশি কাজ করে প্রতিস্থাপন করা যেতে পারে এবং সেগুলি পড়া সহজ।
ডিক্রুট

40

আপনি কেবল এর সাথে ছাঁটাই করতে পারেন echo:

foo=" qsdqsd qsdqs q qs   "

# Not trimmed
echo \'$foo\'

# Trim
foo=`echo $foo`

# Trimmed
echo \'$foo\'

এটি একাধিক স্থিতিশীল স্পেসকে ধসে পড়ে।
এভেজেনি সার্জিভ

7
fooওয়াইল্ডকার্ড থাকা অবস্থায় আপনি কি চেষ্টা করে দেখেছেন ? যেমন, foo=" I * have a wild card"... অবাক! তদ্ব্যতীত এটি একাধিক স্থিতিশীল স্থানগুলি ধসে পড়ে।
gniourf_gniourf

5
এটি একটি দুর্দান্ত সমাধান যদি আপনি: ১. শেষের দিকে কোনও ফাঁকা স্থান চান না ২. প্রতিটি শব্দের মধ্যে একটি মাত্র স্থান চান ৩. কোনও ওয়াইল্ডকার্ড না দিয়ে নিয়ন্ত্রিত ইনপুট নিয়ে কাজ করছেন। এটি মূলত একটি খারাপ ফর্ম্যাট তালিকাটিকে একটি ভালে পরিণত করে।
musicin3d

ওয়াইল্ডকার্ড @gniourf_gniourf +1 এর ভাল অনুস্মারক। এখনও একটি দুর্দান্ত সমাধান, ভ্যাম্প। আপনাকেও +1।
ডাঃ বেকো

25

আমি সবসময় সেড দিয়ে এটি করেছি

  var=`hg st -R "$path" | sed -e 's/  *$//'`

যদি আরও মার্জিত সমাধান হয় তবে আমি আশা করি কেউ এটি পোস্ট করেছে।


আপনি সিনট্যাক্স ব্যাখ্যা করতে পারেন sed?
farid99

2
নিয়মিত এক্সপ্রেশন সমস্ত ট্রেলিং হোয়াইটস্পেসের সাথে মেলে এবং এটিকে কিছু না করে প্রতিস্থাপন করে।
পল টমলিন

4
নেতৃস্থানীয় সাদা স্থান সম্পর্কে কীভাবে?
কিয়ান চেন

এটি সমস্ত পেছনের শ্বেতস্পেসকে বাদ দেয় sed -e 's/\s*$//'। ব্যাখ্যা: 's' এর অর্থ অনুসন্ধান, '\ s' এর অর্থ সমস্ত সাদা স্থান, '*' এর অর্থ শূন্য বা অনেকগুলি, '$' এর অর্থ রেখাটি শেষ হওয়া অবধি এবং '//' এর অর্থ একটি খালি স্ট্রিং সহ সমস্ত মিলের বিকল্প হয় ।
ক্রেগ

'S / * $ //' তে কেন একটি স্থানের পরিবর্তে নক্ষত্রের আগে 2 টি স্থান রয়েছে? এটা কি টাইপো?
ব্রেন্ট 212


24

বাশের এক্সটেন্ডেড প্যাটার্ন মেলানো বৈশিষ্ট্যগুলি সক্ষম করা ( shopt -s extglob) সহ, আপনি এটি ব্যবহার করতে পারেন:

{trimmed##*( )}

নেতৃস্থানীয় স্থানগুলির একটি নির্বিচার পরিমাণ অপসারণ করতে।


ভয়ঙ্কর! আমি মনে করি এটি সবচেয়ে হালকা ও মার্জিত সমাধান।
সন্দেহভাজন জিম

1
অনুরূপ, তবে আরও জেনেরিক সমাধানের জন্য নীচে @ গুরুম এর পোস্টটি দেখুন যা (ক) সমস্ত ধরণের শ্বেত স্থানের সাথে সম্পর্কিত এবং (খ) শ্বেত স্থান অনুসরণ করে পরিচালনা করে।
mklement0

আমার কোড স্নিপেটকে একটি ফাংশন হিসাবে পুনরায় লেখার জন্য সমস্যাটি নেওয়ার জন্য @ এমকেলেট +1। ধন্যবাদ
গুরুএম

ওপেনবিএসডি-র ডিফল্ট / বিন / কেএসএর সাথেও কাজ করে। /bin/sh -o posixখুব কাজ করে তবে আমি সন্দেহজনক।
ক্লিন্ট পাচল

এখানে বাশ উইজার্ড নয়; কি trimmed? এটি কোনও অন্তর্নির্মিত জিনিস বা পরিবর্তনশীল যা ছাঁটা হচ্ছে?
অভিজিৎ সরকার

19
# Trim whitespace from both ends of specified parameter

trim () {
    read -rd '' $1 <<<"${!1}"
}

# Unit test for trim()

test_trim () {
    local foo="$1"
    trim foo
    test "$foo" = "$2"
}

test_trim hey hey &&
test_trim '  hey' hey &&
test_trim 'ho  ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim '  hey  ho  ' 'hey  ho' &&
test_trim $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' &&
test_trim $'\n' '' &&
test_trim '\n' '\n' &&
echo passed

2
অ্যামেজিং! সহজ এবং কার্যকর! পরিষ্কারভাবে আমার প্রিয় সমাধান। ধন্যবাদ!
xebeche

1
@ ক্রেইগম্যাক কিউইন এটি পরিবর্তনশীল মান, readএটির নাম হিসাবে ভেরিয়েবল হিসাবে সংরক্ষণ করবে $ 1 এর মানটির ছাঁটা সংস্করণ} {! 1}
অ্যাকোরিয়াস পাওয়ার

2
ট্রিম () ফাংশনটির প্যারামিটারটি একটি পরিবর্তনশীল নাম: টেস্ট_ট্রিক () এর ভিতরে () ছাঁটাই করতে কলটি দেখুন। টেস্ট_ট্রিম () থেকে ডাকা ট্রিমের () মধ্যে, $ 1 foo এ প্রসারিত হয় এবং 1 {! 1 $ $ foo (অর্থাৎ ভেরিয়েবল foo এর বর্তমান সামগ্রীতে) প্রসারিত হয়। 'ভেরিয়েবল ইন্ডিয়ারেশন' এর জন্য বাশ ম্যানুয়ালটি সন্ধান করুন।
ফ্ল্যাবডব্লেট

1
এই কলে সংশোধন সম্পর্কে কীভাবে, এক কলের একাধিক ওয়ার ট্রিমিং সমর্থন করতে? trim() { while [[ $# -gt 0 ]]; do read -rd '' $1 <<<"${!1}"; shift; done; }
জিন পাভলোভস্কি

2
@ অ্যাকোয়ারিয়াস পাওয়ারের ওয়ান-লাইনার সংস্করণের জন্য সাব-শেলের প্রতিধ্বনি ব্যবহার করার দরকার নেই, কেবল এটিই read -rd '' str <<<"$str"করবে।
ফ্ল্যাবলেটসলেট

12

অনেক উত্তর আছে, তবে আমি এখনও বিশ্বাস করি যে আমার সবে-লিখিত স্ক্রিপ্টটি উল্লেখযোগ্য কারণ কারণ:

  • এটি সফলভাবে শেল বাশ / ড্যাশ / ব্যস্তবক্স শেলটিতে পরীক্ষা করা হয়েছিল
  • এটা অত্যন্ত ছোট
  • এটি বাহ্যিক আদেশের উপর নির্ভর করে না এবং - (-> দ্রুত এবং স্বল্প সংস্থান ব্যবহারের) কাঁটাচামচ করার দরকার নেই
  • এটি প্রত্যাশার মতো কাজ করে:
    • এটি শুরু এবং শেষ থেকে সমস্ত স্পেস এবং ট্যাবগুলি ফেলা করে তবে আরও বেশি নয়
    • গুরুত্বপূর্ণ: এটি স্ট্রিংয়ের মাঝামাঝি থেকে কোনও কিছুই সরিয়ে দেয় না (অন্য অনেক উত্তর দেয়), এমনকি নিউলাইনগুলি থাকবে
    • বিশেষ: "$*"একটি স্পেস ব্যবহার করে একাধিক তর্ক যুক্ত হয়। যদি আপনি কেবল প্রথম আর্গুমেন্টটি ছাঁটাই করতে এবং আউটপুট করতে চান তবে "$1"পরিবর্তে ব্যবহার করুন
    • ফাইলের নামের ধরণ ইত্যাদি মিলে যদি কোনও সমস্যা না হয়

এই পান্ডুলিপি:

trim() {
  local s2 s="$*"
  until s2="${s#[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  until s2="${s%[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
  echo "$s"
}

ব্যবহার:

mystring="   here     is
    something    "
mystring=$(trim "$mystring")
echo ">$mystring<"

আউটপুট:

>here     is
    something<

বাহ ইন সি এটি বাস্তবায়ন সহজ উপায় হবে!
নিলস

অবশ্যই। দুর্ভাগ্যক্রমে, এটি সি নয় এবং কখনও কখনও আপনি বাহ্যিক সরঞ্জামগুলি কল করা এড়াতে চান
ড্যানিয়েল অল্ডার

কোডটি আরও পঠনযোগ্য এবং অনুলিপি-অতীতের উভয়ই সামঞ্জস্যপূর্ণ করতে আপনি বন্ধনীগুলি পালিয়ে যাওয়া চরিত্রগুলিতে পরিবর্তন করতে পারেন:[\ \t]
লন্ডিপিয়ন

আপনি কি এটি চেষ্টা করেছেন? আমি যখন এটি লিখেছিলাম এবং আবার চেষ্টা করেছি তখন আমি চেষ্টা করেছি এবং আপনার পরামর্শ কোনও ব্যাশ, ড্যাশ, ব্যস্তবক্সে কাজ করে না
ড্যানিয়েল অ্যাল্ডার

@ ড্যানিয়েল অ্যাল্ডার আমি করেছিলাম, তবে এটি 3 বছর আগে ইতিমধ্যে, আমি যেখানে কোডটি ব্যবহার করেছি সেটি খুঁজে পাচ্ছি না। এখন অবশ্য আমি সম্ভবত ব্যবহার করতে চাই [[:space:]]: মত অন্যান্য উত্তর এক stackoverflow.com/a/3352015/3968618
leondepeon

11

আপনি পুরানো স্কুল ব্যবহার করতে পারেন tr। উদাহরণস্বরূপ, এটি একটি গিট সংগ্রহস্থলগুলিতে পরিবর্তিত ফাইলগুলির সংখ্যা প্রদান করে, হোয়াইটস্পেসগুলি বাদ দেওয়া।

MYVAR=`git ls-files -m|wc -l|tr -d ' '`

1
এটি সামনে এবং পিছন থেকে সাদা স্থান ট্রিম করে না - এটি স্ট্রিং থেকে সমস্ত সাদা স্থান সরিয়ে দেয়।
নিক

11

এটি আমার পক্ষে কাজ করেছে:

text="   trim my edges    "

trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back

echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed

#Result
<trim my edges>

একই ফলাফলের জন্য এটি কম লাইনে রাখার জন্য:

text="    trim my edges    "
trimmed=${${text##+( )}%%+( )}

1
আমার পক্ষে কাজ করেনি। প্রথমটি একটি নিরবচ্ছিন্ন স্ট্রিং প্রিন্ট করেছে। দ্বিতীয়টি খারাপ প্রতিস্থাপন ছুড়েছিল। এখানে কী চলছে তা আপনি ব্যাখ্যা করতে পারেন?
musicin3d

1
@ মিউজিকিন 3 ডি: এটি এমন একটি সাইট যা আমি প্রায়শই ব্যবহার করি যা আরও বিশদ অনুসন্ধানের জন্য ব্যাশ অনুসন্ধানে পরিবর্তনশীল ম্যানিপুলেশন কীভাবে কাজ করে তা স্পੈਲ করে ${var##Pattern}। এছাড়াও, এই সাইটটি ব্যাশের নিদর্শনগুলি ব্যাখ্যা করে । সুতরাং ##উপায়গুলি সামনে থেকে প্রদত্ত প্যাটার্নটি সরিয়ে দেবে এবং এর %%অর্থ পিছনে থেকে প্রদত্ত প্যাটার্নটি সরান। +( )অংশ প্যাটার্ন এবং এটি "এক বা স্থান আরো সংঘটন" অর্থ
gMale

মজার বিষয়, এটি প্রম্পটে কাজ করেছে, তবে ব্যাশ স্ক্রিপ্ট ফাইলটিতে স্থানান্তরিত করার পরে নয়।
ডাঃ বেকো

অদ্ভুত। এটি উভয় ক্ষেত্রে একই বাশ সংস্করণ?
gMale

11
# Strip leading and trailing white space (new line inclusive).
trim(){
    [[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]]
    printf "%s" "$BASH_REMATCH"
}

অথবা

# Strip leading white space (new line inclusive).
ltrim(){
    [[ "$1" =~ [^[:space:]].* ]]
    printf "%s" "$BASH_REMATCH"
}

# Strip trailing white space (new line inclusive).
rtrim(){
    [[ "$1" =~ .*[^[:space:]] ]]
    printf "%s" "$BASH_REMATCH"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1")")"
}

অথবা

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

অথবা

# Strip leading specified characters.  ex: str=$(ltrim "$str" $'\n a')
ltrim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

# Strip trailing specified characters.  ex: str=$(rtrim "$str" $'\n a')
rtrim(){
    if [ "$2" ]; then
        trim_chrs="$2"
    else
        trim_chrs="[:space:]"
    fi

    [[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]]
    printf "%s" "${BASH_REMATCH[1]}"
}

# Strip leading and trailing specified characters.  ex: str=$(trim "$str" $'\n a')
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")"
}

অথবা

মোসকিটের এক্সপ্রেরাল আধ্যাত্মিক উদ্যোগের উপর ভিত্তি করে ...

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`"
}

অথবা

# Strip leading white space (new line inclusive).
ltrim(){
    printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`"
}

# Strip trailing white space (new line inclusive).
rtrim(){
    printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`"
}

# Strip leading and trailing white space (new line inclusive).
trim(){
    printf "%s" "$(rtrim "$(ltrim "$1")")"
}

8

আমি স্ক্রিপ্টগুলি দেখেছি মাত্র কাজটি করতে ভেরিয়েবল অ্যাসাইনমেন্টটি ব্যবহার করে:

$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar

হোয়াইটস্পেস স্বয়ংক্রিয়ভাবে coalesced এবং ছাঁটা হয়। শেল মেটাচার্যাক্টরগুলি (সম্ভাব্য ইনজেকশন ঝুঁকি) সম্পর্কে সতর্কতা অবলম্বন করতে হবে।

আমি সর্বদা শেল শর্তসাপেক্ষে ভেরিয়েবল বিকল্পগুলি ডাবল-কোটিংয়ের সুপারিশ করব:

if [ -n "$var" ]; then

যেহেতু ভেরিয়েবলের -o বা অন্যান্য সামগ্রীর মতো কিছু আপনার পরীক্ষার যুক্তি সংশোধন করতে পারে।


3
এটা unquoted ব্যবহার $xyzসঙ্গে echoযে হোয়াইটস্পেস কোয়ালেসিং, না না পরিবর্তনশীল নিয়োগ। আপনার উদাহরণে ভেরিয়েবলের ছাঁটা মান সংরক্ষণ করতে, আপনাকে ব্যবহার করতে হবে xyz=$(echo -n $xyz)। এছাড়াও, এই পদ্ধতির সম্ভাব্য অযাচিত পথের নাম সম্প্রসারণ (গ্লোববিং) সাপেক্ষে।
mklement0

এটি পাট ভুল, xyzভেরিয়েবলের মান ছাঁটা হয় না।
সিজারসোল

7
var='   a b c   '
trimmed=$(echo $var)

1
যে কোনও দুটি শব্দের মধ্যে একাধিক স্থান থাকলে এটি কাজ করবে না। চেষ্টা করুন: echo $(echo "1 2 3")(1, 2 এবং 3 এর মধ্যে দুটি স্পেস সহ)।
জোশল্ফ

7

আমি কেবল সেড ব্যবহার করব:

function trim
{
    echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}

ক) একক লাইন স্ট্রিং ব্যবহারের উদাহরণ

string='    wordA wordB  wordC   wordD    '
trimmed=$( trim "$string" )

echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"

আউটপুট:

GIVEN STRING: |    wordA wordB  wordC   wordD    |
TRIMMED STRING: |wordA wordB  wordC   wordD|

খ) মাল্টি-লাইন স্ট্রিংয়ের ব্যবহারের উদাহরণ

string='    wordA
   >wordB<
wordC    '
trimmed=$( trim "$string" )

echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"

আউটপুট:

GIVEN STRING: |    wordAA
   >wordB<
wordC    |

TRIMMED STRING: |wordAA
   >wordB<
wordC|

গ) চূড়ান্ত দ্রষ্টব্য:
আপনি যদি কোনও ফাংশন ব্যবহার করতে না চান তবে একক-লাইনের স্ট্রিংয়ের জন্য আপনি কেবল "সহজ মনে রাখা সহজ" কমান্ডটি ব্যবহার করতে পারেন:

echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

উদাহরণ:

echo "   wordA wordB wordC   " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

আউটপুট:

wordA wordB wordC

ব্যবহারের উপরে বহু-লাইন স্ট্রিং পাশাপাশি কাজ করবে , কিন্তু মনে রাখবেন যে কোনো চিহ্ন থেকে কর্তন করব / পাশাপাশি অভ্যন্তরীণ একাধিক স্থান নেতৃস্থানীয়, যেমন GuruM মন্তব্য খেয়াল খুশি

string='    wordAA
    >four spaces before<
 >one space before<    '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

আউটপুট:

wordAA
>four spaces before<
>one space before<

সুতরাং যদি আপনি এই শূন্যস্থানগুলি রাখার কথা মনে করেন তবে দয়া করে আমার উত্তরের শুরুতে ফাংশনটি ব্যবহার করুন!

ঘ) ফাংশন ট্রিমের অভ্যন্তরে ব্যবহৃত মাল্টি-লাইন স্ট্রিংগুলিতে "সন্ধান করুন এবং প্রতিস্থাপন করুন" সিনড্যাক্সের বিবরণ:

sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
    # Copy from the hold to the pattern buffer
    g
    # Do the search and replace
    s/^[ \t]*//g
    s/[ \t]*$//g
    # print
    p
}'

দ্রষ্টব্য: @ মেকলেটের পরামর্শ অনুসারে এটি মাল্টি-লাইন স্ট্রিংয়ের জন্য কাজ করবে না যদিও এটি একক-লাইন স্ট্রিংয়ের জন্য কাজ করা উচিত।
গুরুএম

1
আপনি ভুল: এটি বহু-লাইনের স্ট্রিংগুলিতেও কাজ করে। কেবল এটি পরীক্ষা করে দেখুন! :)
লুকা বোররিওন

ব্যবহারের জন্য +1 - কোডটি পরীক্ষা করা আমার পক্ষে সহজ করে দিয়েছে। তবে কোডটি এখনও বহু-লাইন স্ট্রিংয়ের জন্য কাজ করবে না। যদি আপনি আউটপুটটি মনোযোগ সহকারে দেখেন তবে আপনি লক্ষ্য করবেন যে কোনও শীর্ষস্থানীয় / পশ্চাদপসরণ অভ্যন্তরীণ স্থানগুলিও সরিয়ে যাচ্ছে যেমন "" বহু-লাইন "এর সামনের স্থানটি" ​​মাল্টি-লাইন "দ্বারা প্রতিস্থাপন করা হয়েছে। প্রতিটি লাইনে কেবল শীর্ষস্থানীয় / পিছনের জায়গাগুলির সংখ্যা বাড়ানোর চেষ্টা করুন।
গুরুএম

এখন আমি কি বলতে চাইছি! মাথা আপ জন্য আপনাকে ধন্যবাদ, আমি আমার উত্তর সম্পাদনা।
লুকা বোরিওনিয়ান

@ "লুকা বোররিওন" - স্বাগত :-) আপনি কি ছাঁটা বাক্সটি ছাঁটাচ্ছেন ()? এটি আপনার কোডের যে কোনও ব্যবহারকারীর এটিকে অন্য ব্যবহারগুলিতে টুইঙ্ক করতে সহায়তা করতে পারে। এছাড়াও এটি নিয়মিত-এক্সপ্রেশন জন্য প্রান্ত-কেস সন্ধান করতে সহায়তা করতে পারে।
গুরুএম

6

এখানে একটি ছাঁটাই () ফাংশন যা সাদা স্থানকে ছাঁটাই করে এবং স্বাভাবিক করে তোলে

#!/bin/bash
function trim {
    echo $*
}

echo "'$(trim "  one   two    three  ")'"
# 'one two three'

এবং অন্য একটি রূপ যা নিয়মিত প্রকাশ করে।

#!/bin/bash
function trim {
    local trimmed="$@"
    if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
    then 
        trimmed=${BASH_REMATCH[1]}
    fi
    echo "$trimmed"
}

echo "'$(trim "  one   two    three  ")'"
# 'one   two    three'

প্রথম পদ্ধতির কৌশলটি জটিল যে এটি কেবল অভ্যন্তরীন সাদা স্থানকেই স্বাভাবিক করে তোলে না (প্রতিটি স্থানের অভ্যন্তরের সাদা অংশকে একটি একক জায়গার সাথে প্রতিস্থাপন করে), তবে গ্লোব্বিংয়ের (প্যাথনাম এক্সপেনশন) সাপেক্ষে যাতে উদাহরণস্বরূপ, *ইনপুট স্ট্রিংয়ের একটি অক্ষর হবে বর্তমান ওয়ার্কিং ফোল্ডারে সমস্ত ফাইল এবং ফোল্ডারগুলিতে প্রসারিত করুন। অবশেষে, যদি FS আইএফএস একটি অ-ডিফল্ট মানতে সেট করা থাকে তবে ট্রিমিং কাজ নাও করতে পারে (যদিও এটি যোগ করে সহজেই প্রতিকার করা হয়local IFS=$' \t\n' )। ছাঁটাইটি হোয়াইটস্পেসের নিম্নলিখিত ফর্মগুলির মধ্যে সীমাবদ্ধ: স্পেস,\t এবং \nঅক্ষর।
mklement0

1
দ্বিতীয়টি, নিয়মিত প্রকাশ-ভিত্তিক পদ্ধতির দুর্দান্ত এবং পার্শ্ব প্রতিক্রিয়া মুক্ত, তবে এর বর্তমান ফর্মটি সমস্যাযুক্ত: (ক) ব্যাশ ভি 3.2 +-তে, মিলটি ডিফল্টরূপে কাজ করবে না, কারণ নিয়মিত অভিব্যক্তিটি অবশ্যই ক্রমযুক্ত হওয়া উচিত কাজ করার জন্য এবং (খ) নিয়মিত এক্সপ্রেশন নিজেই কেসটি পরিচালনা করে না যেখানে ইনপুট স্ট্রিংটি ফাঁকা দ্বারা ঘেরা একক, অ-স্থানের অক্ষর। এই সমস্যাগুলি সমাধান করতে, ifলাইনটি এর সাথে প্রতিস্থাপন করুন :if [[ "$trimmed" =~ ' '*([^ ]|[^ ].*[^ ])' '* ]] । পরিশেষে, পদ্ধতির কেবল স্থানগুলির সাথে সম্পর্কিত হয়, অন্য ধরণের শ্বেতপথের সাথে নয় (আমার পরবর্তী মন্তব্য দেখুন)।
mklement0

2
নিয়মিত এক্সপ্রেশন ব্যবহার করে এমন ফাংশনটি কেবল ফাঁকা জায়গাগুলির সাথে সম্পর্কিত করে অন্য ধরণের শ্বেত স্পেসের সাথে সম্পর্কিত নয় তবে সাধারণকরণ করা সহজ: ifলাইনটি এর সাথে প্রতিস্থাপন করুন :[[ "$trimmed" =~ [[:space:]]*([^[:space:]]|[^[:space:]].*[^[:space:]])[[:space:]]* ]]
এমকিলেমেন্ট 0

6

AWK ব্যবহার করুন:

echo $var | awk '{gsub(/^ +| +$/,"")}1'

মিষ্টি যা কাজ করে বলে মনে হচ্ছে (প্রাক্তন :) $stripped_version=প্রতিধ্বনি $ awk '{gsub (/ ^ + | + $ /, "")} 1'``
রোজারডপ্যাক

4
অ্যাজক ব্যতীত কিছু করছে না: অব্যবহৃত ভেরিয়েবল প্রতিধ্বনি করা ইতিমধ্যে হোয়াইটস্পেস ছিনিয়ে নিয়েছে
গ্লেন জ্যাকম্যান

6

অ্যাসাইনমেন্টগুলি শীর্ষস্থানীয় এবং অনুসরণযোগ্য শ্বেত স্পেস উপেক্ষা করে এবং এর মতো ছাঁটাতে ব্যবহার করা যেতে পারে:

$ var=`echo '   hello'`; echo $var
hello

8
এটা সত্যি না. এটি "প্রতিধ্বনি" যা অ্যাসাইনমেন্টটি নয়, সাদা স্থান সরিয়ে দেয়। আপনার উদাহরণে, echo "$var"স্পেস সহ মানটি দেখুন।
নিকোলাস সুসকিন

2
@ নিকোলাস সুসকিন একটি করতে পারে var=$(echo $var)তবে আমি এটির প্রস্তাব দিই না। এখানে উপস্থাপন করা অন্যান্য সমাধান পছন্দ করা হয়।
xebeche

5

এটি অযাচিত গ্লোব্বিংয়ের সাথে সমস্যা নেই, এছাড়াও, অভ্যন্তর সাদা স্থানটি অবিস্মরণযুক্ত (ধরে নিলেন যে $IFSএটি ডিফল্টে সেট করা আছে, যা ' \t\n')।

এটি প্রথম নিউলাইন পর্যন্ত পড়ে (এবং এটি অন্তর্ভুক্ত করে না) বা স্ট্রিংয়ের শেষে, যেটি প্রথমে আসে এবং শীর্ষস্থানীয় এবং পিছনের স্থান এবং \tঅক্ষরগুলির কোনও মিশ্রণ সরিয়ে ফেলে । আপনি যদি একাধিক লাইন সংরক্ষণ করতে চান (এবং শীর্ষস্থানীয় এবং পেছনের নতুন লাইনের স্ট্রিপও), read -r -d '' var << eofপরিবর্তে ব্যবহার করুন; তবে নোট করুন, আপনার ইনপুটটি যদি এমনটি ঘটে থাকে তবে \neofএটি ঠিক আগেই কেটে ফেলা হবে। (সাদা স্থান, যথা অন্য ফর্ম \r, \fএবং \v, হয় না ছিনতাই, এমনকি যদি আপনি তাদের $ IFS যোগ করুন।)

read -r var << eof
$var
eof


5

এটি আপনার স্ট্রিং থেকে সমস্ত সাদা জায়গা সরিয়ে ফেলবে,

 VAR2="${VAR2//[[:space:]]/}"

/প্রথম ঘটনাটি এবং //স্ট্রিংয়ের সাদা অংশগুলির সমস্ত উপস্থিতি প্রতিস্থাপন করে । অর্থাৎ সমস্ত সাদা স্পেসগুলি প্রতিস্থাপন করে - কিছুই না nothing


4

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

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

এটি পরীক্ষা করার জন্য এখানে একটি নমুনা স্ক্রিপ্ট রয়েছে:

test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t  \n ")

echo "Let's see if this works:"
echo
echo "----------"
echo -e "Testing:${test} :Tested"  # Ugh!
echo "----------"
echo
echo "Ugh!  Let's fix that..."

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

echo
echo "----------"
echo -e "Testing:${test}:Tested"  # "Testing:Spaces and tabs and newlines be gone!"
echo "----------"
echo
echo "Ah, much better."

1
উদাহরণস্বরূপ (উদাহরণস্বরূপ (godsশ্বরগণ!), পাইথনের দিকে গোলাবর্ষণ করা অবশ্যই পছন্দনীয়। কেবলমাত্র স্পেস রয়েছে এমন স্ট্রিং সঠিকভাবে পরিচালনা করা সহজ এবং আরও সাধারণ হিসাবে আমি মনে করি light কিছুটা সরলিকৃত ভাবটি হবে:^[[:space:]]*(.*[^[:space:]])?[[:space:]]*$
রন বার্ক

4

পাইথনের একটি ফাংশন রয়েছে strip()যা পিএইচপি'র সাথে অভিন্নভাবে কাজ করে trim(), তাই এর জন্য সহজেই বোধগম্য ইউটিলিটিটি তৈরি করতে আমরা কেবল কিছুটা ইনলাইন পাইথন করতে পারি:

alias trim='python -c "import sys; sys.stdout.write(sys.stdin.read().strip())"'

এটি শীর্ষস্থানীয় এবং পিছনের শ্বেত স্পেসটি ট্রিম করবে (নিউলাইনগুলি সহ)।

$ x=`echo -e "\n\t   \n" | trim`
$ if [ -z "$x" ]; then echo hi; fi
hi

এটি যখন কাজ করে, আপনি এমন একটি সমাধান দেওয়ার প্রস্তাব বিবেচনা করতে পারেন যা কেবল একটি স্ট্রিং ছাঁটাই করার জন্য একটি পূর্ণ অজগর দোভাষীকে জড়িত না। এটা ঠিক অপচয়।
pdwalker

3
#!/bin/bash

function trim
{
    typeset trimVar
    eval trimVar="\${$1}"
    read trimVar << EOTtrim
    $trimVar
EOTtrim
    eval $1=\$trimVar
}

# Note that the parameter to the function is the NAME of the variable to trim, 
# not the variable contents.  However, the contents are trimmed.


# Example of use:
while read aLine
do
    trim aline
    echo "[${aline}]"
done < info.txt



# File info.txt contents:
# ------------------------------
# ok  hello there    $
#    another  line   here     $
#and yet another   $
#  only at the front$
#$



# Output:
#[ok  hello there]
#[another  line   here]
#[and yet another]
#[only at the front]
#[]

3

আমি দেখতে পেয়েছি যে sdiffএটি পরিষ্কার করার জন্য আমার একটি অগোছালো আউটপুট থেকে কিছু কোড যুক্ত করা দরকার:

sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt 
sed -n 1'p' c12diff.txt | sed 's/ *$//g' | tr -d '\n' | tr -d '\t'

এটি পেছনের স্থান এবং অন্যান্য অদৃশ্য অক্ষরগুলি সরিয়ে দেয়।


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