বাশে কোনও চলককে হেরডোক মানটি কীভাবে অর্পণ করতে?


374

আমার এই মাল্টি-লাইন স্ট্রিং রয়েছে (উদ্ধৃতিগুলি অন্তর্ভুক্ত):

abc'asdf"
$(dont-execute-this)
foo"bar"''

বাশে হেরেডোক ব্যবহার করে আমি কীভাবে এটি পরিবর্তনশীলকে নির্ধারণ করব?

আমার নতুন লাইনের সংরক্ষণ করা দরকার।

আমি স্ট্রিংয়ের অক্ষরগুলি থেকে পালাতে চাই না, এটি বিরক্তিকর হবে ...


@ জনম - আমি সিডি` কমান্ডের 'EOF'সাহায্যে পালিয়ে যাওয়া লাইনব্রেক সহ ` in the content: if the second line has সবেমাত্র একক উদ্ধৃত সহ একটি বংশগত কার্যনির্বাহী চেষ্টা করেছি , আমি ফিরে পেয়েছি: " .শ: লাইন এক্স: সিডি: কমান্ড পাওয়া যায় নি "; তবে আমি যদি ডাবল-কোট করি "EOF"; তারপরে ব্যাশ ভেরিয়েবলগুলি ${A}স্ট্রিং হিসাবে সংরক্ষণ করা হয় না (সেগুলি প্রসারিত হয়); কিন্তু তারপর, লাইন-বিরতি হয় সংরক্ষিত - এবং, আমি একটি সমস্যা কমান্ড চলমান হবে না cdদ্বিতীয় লাইনে ( এবং উভয় 'ফাইলের শেষে' এবং "ফাইলের শেষে" ভাল এছাড়াও সঙ্গে খেলা বলে মনে হচ্ছে evalসঞ্চিত কমান্ড একটি সেট চালানোর জন্য, একটি স্ট্রিং ভেরিয়েবল )। চিয়ার্স!
sdaau

1
... এবং আমার পূর্ববর্তী মন্তব্যে যোগ করার জন্য: ডাবল-কউয়েটেড "EOF"ভেরিয়েবলে বাশ মন্তব্য "#" , যদি এটির মাধ্যমে ডাকা হয়, তবে eval $VARস্ক্রিপ্টের সমস্ত অংশকেই মন্তব্য করা হবে, কারণ এখানে AR ভিএআর একটি একক লাইন হিসাবে দেখা যাবে ; #মাল্টিলাইন স্ক্রিপ্টে ব্যাশ মন্তব্যগুলি ব্যবহার করতে সক্ষম হতে , ডাবল-উদ্ধৃতিটি eval call: "al VAR" in এও পরিবর্তনশীল in
sdaau

@ এসডাউ: আমার evalএই পদ্ধতিগুলির সাথে সমস্যা হয়েছিল , তবে এটি ট্র্যাক করে নিই না কারণ এটি কিছু প্যাকেজের অংশ ছিল যা evalএর কনফিগার ফাইলটিতে কিছু ভেরিয়েবল সংজ্ঞায়িত হয়েছিল। ত্রুটি সংক্রান্ত বার্তা: /usr/lib/network/network: eval: line 153: syntax error: unexpected end of file। আমি সবেমাত্র অন্য একটি সমাধানে স্যুইচ করেছি।
গোলার র‌্যামব্লার

উত্তর:


515

আপনি এর সাথে অপ্রয়োজনীয় catউদ্ধৃতিগুলির অপ্রয়োজনীয় ব্যবহার এড়াতে এবং হ্যান্ডেল করতে পারেন :

$ read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF

আপনি যদি প্রতিধ্বনিত হওয়ার সময় ভেরিয়েবলটি উদ্ধৃত না করেন তবে নিউলাইনগুলি হারিয়ে যাবে। এটিকে উদ্ধৃত করা তাদের সংরক্ষণ করে:

$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''

যদি আপনি উত্স কোডে পঠনযোগ্যতার জন্য ইন্ডেন্টেশন ব্যবহার করতে চান তবে কম-থ্যান্সের পরে একটি ড্যাশ ব্যবহার করুন। ইন্ডেন্টেশনটি কেবলমাত্র ট্যাব ব্যবহার করেই করা উচিত (কোনও স্থান নেই)।

$ read -r -d '' VAR <<-'EOF'
    abc'asdf"
    $(dont-execute-this)
    foo"bar"''
    EOF
$ echo "$VAR"
abc'asdf"
$(dont-execute-this)
foo"bar"''

পরিবর্তে, আপনি ফলস্বরূপ ভেরিয়েবলের বিষয়বস্তুতে ট্যাবগুলি সংরক্ষণ করতে চান, আপনাকে এ থেকে ট্যাব সরিয়ে ফেলতে হবে IFS। এখানে ডক ( EOF) এর জন্য টার্মিনাল চিহ্নিতকারী অবশ্যই ইনডেন্ট হওয়া উচিত নয়।

$ IFS='' read -r -d '' VAR <<'EOF'
    abc'asdf"
    $(dont-execute-this)
    foo"bar"''
EOF
$ echo "$VAR"
    abc'asdf"
    $(dont-execute-this)
    foo"bar"''

কমান্ড লাইনে ট্যাবগুলি সন্নিবেশ করা যেতে পারে Ctrl- - টিপুন দ্বারা V Tab। আপনি যদি কোনও সম্পাদক ব্যবহার করছেন তবে কোনটির উপর নির্ভর করে, এটিও কাজ করতে পারে বা ট্যাবগুলিকে স্বয়ংক্রিয়ভাবে স্থানগুলিতে রূপান্তর করে এমন বৈশিষ্ট্যটি আপনাকে বন্ধ করতে হতে পারে।


117
আমি মনে করি এটি উল্লেখ করার মতো যে যদি আপনার স্ক্রিপ্টে set -o errexit(ওরফে set -e) থাকে এবং আপনি এটি ব্যবহার করেন তবে এটি আপনার স্ক্রিপ্টটি সমাপ্ত করবে কারণ readএটি ইওএফ পৌঁছানোর পরে একটি শূন্য নয় এমন রিটার্ন কোড দেয়।
মার্ক বাইয়ার্স

14
@ মার্কবায়ার্স: এটি অন্যতম কারণ যা আমি কখনই ব্যবহার করি না set -eএবং সর্বদা এর ব্যবহারের বিরুদ্ধে সুপারিশ করি। পরিবর্তে যথাযথ ত্রুটি হ্যান্ডলিং ব্যবহার করা ভাল। trapতোমার বন্ধু. অন্যান্য বন্ধুরা: elseএবং ||অন্যদের মধ্যে।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

7
catএরকম ক্ষেত্রে কী এড়ানো সত্যিই মূল্যবান? একটি ভেরিয়েবলের সাথে একটি হেরডোক বরাদ্দ করা একটি catসুপরিচিত প্রতিমা। কিছুটা হলেও readসামান্য উপকারের জন্য জিনিসগুলিকে অবিচ্ছিন্ন করে im
গ্রেগরি পাকোসজ

6
@ulidtko এর কারণ আপনার dখালি স্ট্রিংয়ের মধ্যে কোনও স্থান নেই ; এর আর্গুমেন্টগুলি দেখার আগে কেবল bashধসে পড়ে তাই আর্গুমেন্ট হিসাবে বিবেচিত হয় । -rd''-rdreadVAR-d
চিপনার

6
এই বিন্যাসে, readএকটি শূন্য-বহির্গমন কোড সহ ফিরে আসবে। এটি ত্রুটি যাচাইকরণ সক্ষম (উদাহরণস্বরূপ set -e) সহ কোনও স্ক্রিপ্টে এই পদ্ধতির চেয়ে কম আদর্শ করে তোলে ।
সুইস

245

catআপনার ভেরিয়েবলের আউটপুট এভাবে নির্ধারণ করতে $ () ব্যবহার করুন :

VAR=$(cat <<'END_HEREDOC'
abc'asdf"
$(dont-execute-this)
foo"bar"''
END_HEREDOC
)

# this will echo variable with new lines intact
echo "$VAR"
# this will echo variable without new lines (changed to space character)
echo $VAR

একক উদ্ধৃতি দিয়ে END_HEREDOC শুরু করে সীমানা নিশ্চিত করা।

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

@ephemientউত্তরের জন্য ধন্যবাদ ।


1
আসলে, এই এক কিছু পরিস্থিতিতে উদ্ধৃতি দিয়ে দেয়। আমি পার্লে এটি সহজেই পরিচালনা করতে পেরেছি ...
নিল

32
+1 টি। অন্তত আমার চোখের জন্য এটি সর্বাধিক পঠনযোগ্য সমাধান। এটি পঠনের কমান্ডে এমবেড না করে পৃষ্ঠের বহি বামে ভেরিয়েবলের নাম রেখে দেয়।
ক্লেটন স্ট্যানলি

12
পিএসএ: মনে রাখবেন ভেরিয়েবলটি অবশ্যই নতুন লাইনের সংরক্ষণের জন্য উদ্ধৃত করা উচিতecho "$VAR"পরিবর্তে echo $VAR
সেভকো

7
এটি দুর্দান্ত ashএবং ওপেনডব্লিউআরটি যেখানে readসমর্থন করে না -d
ডেভিড এহরমান

3
কারণে আমি Fathom, এই একটি "অপ্রত্যাশিত ফাইলের শেষে" ত্রুটি সঙ্গে ব্যর্থ পারেন যদি আপনি একটি আছে বিজোড় heredoc মধ্যে ব্যাকটিক।
রেডন রোজবরো 0

79

এটি ডেনিস পদ্ধতির ভিন্নতা, স্ক্রিপ্টগুলিতে আরও মার্জিত দেখাচ্ছে।

ফাংশন সংজ্ঞা:

define(){ IFS='\n' read -r -d '' ${1} || true; }

ব্যবহার:

define VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF

echo "$VAR"

উপভোগ

সমর্থন করে না এমন শেলগুলির জন্য PS একটি 'রিড লুপ' সংস্করণ তৈরি করেছে read -dব্যাকটিক্সের সাথে set -euএবং অযৌক্তিক ব্যাকটিকগুলি নিয়ে কাজ করা উচিত , তবে খুব ভাল পরীক্ষিত নয়:

define(){ o=; while IFS="\n" read -r a; do o="$o$a"'
'; done; eval "$1=\$o"; }

1
এটি কেবলমাত্র পর্যাপ্তরূপে কাজ করে বলে মনে হচ্ছে। সংজ্ঞায়িত ফাংশনটি 1 এর স্থিতি ফিরিয়ে দেবে এবং আমি কী ঠিক করতে হবে তা পুরোপুরি নিশ্চিত নই।
fny

1
এটি গ্রহণযোগ্য উত্তরের চেয়েও উন্নত, কারণ এটি পশিক্স শকে সমর্থন করার পাশাপাশি সংশোধন করা যেতে পারে ( নিউলাইনগুলি সংরক্ষণের জন্য প্রয়োজনীয় বাশিজম readএড়াতে ফাংশনটির একটি লুপ -d '')।
এলিওটিটিসিবিবল

ক্যাট-ইন-এ-সাবসেল বিকল্পের বিপরীতে, এটি হেরডোকে আনপায়ার্ড ব্যাকটিক্সের সাথে কাজ করে । ধন্যবাদ!
রেডন রোসবারো

এই সমাধানটি set -eসেট সহ কাজ করে , যেখানে নির্বাচিত উত্তর দেয় না। কারণ এটি মনে করা হয়http://unix.stackexchange.com/a/265151/20650
ffledgling

2
@fny পিএস রিটার্নের স্থিতি দীর্ঘকাল স্থির করা হয়েছে
ttt

36
VAR=<<END
abc
END

কাজ করে না কারণ আপনি স্টিডিনকে এমন কোনও কিছুতে পুনঃনির্দেশ করছেন যা অ্যাসাইনমেন্ট

export A=`cat <<END
sdfsdf
sdfsdf
sdfsfds
END
` ; echo $A

কাজ করে, তবে সেখানে একটি ব্যাক-টিক রয়েছে যা আপনাকে এটি ব্যবহার করা থেকে বিরত করতে পারে। এছাড়াও, আপনার ব্যাকটিক্স ব্যবহার করা সত্যিই এড়ানো উচিত, কমান্ড প্রতিস্থাপন স্বরলিপি ব্যবহার করা ভাল $(..)

export A=$(cat <<END
sdfsdf
sdfsdf
sdfsfds
END
) ; echo $A

আমি আমার প্রশ্ন আপডেট করেছি (এক্সিকিউটেবল) অন্তর্ভুক্ত করতে। এছাড়াও, আপনি কীভাবে নিউলাইনগুলি সংরক্ষণ করবেন?
নিল

2
@ l0st3d: এত কাছে ... $(cat <<'END'পরিবর্তে ব্যবহার করুন @ নীল: একেবারে শেষ নিউলাইনটি ভেরিয়েবলের অংশ হবে না, তবে বাকিটি সংরক্ষণ করা হবে।
মুহূর্তে

1
মনে হচ্ছে কোনও নতুনলাইন সংরক্ষণ করা নেই। উপরের উদাহরণটি চালানো আমি দেখতে পাচ্ছি: "sdfsdf sdfsdf sdfsfds" ... আহ! তবে লিখন echo "$A"(অর্থাত্ ডাবল উদ্ধৃতিতে $ এ লাগানো) এবং আপনি নতুন লাইনগুলি দেখতে পাচ্ছেন!
ড্যারেন কুক

1
@ ড্যারেন: আহা! আমি নিউলাইনস ইস্যুটি লক্ষ্য করেছি এবং আউটপুট ভেরিয়েবলের চারপাশে উদ্ধৃতিগুলি ব্যবহার করা সমস্যার সমাধান করে। ধন্যবাদ!
জাভাদবা

1
মজার ব্যাপার হচ্ছে, প্রথম উদাহরণস্বরূপ ছল কারণে একটি চিম্টি মধ্যে আপনি এটা ভালো অস্থায়ী মন্তব্য ব্লক জন্য ব্যবহার করতে পারেন: REM=<< 'REM' ... comment block goes here ... REM। বা আরও সংক্ষিপ্তভাবে : << 'REM' ...,। যেখানে "আরইএম" "নোটস" বা "এসসিআরএটিচপিএড" ইত্যাদির মতো হতে পারে
বিজেজর

34

নিউলাইনগুলি সংরক্ষণ করে এমন কোনও সমাধান এখনও নেই।

এটি সত্য নয় - আপনি সম্ভবত প্রতিধ্বনির আচরণ দ্বারা বিভ্রান্ত হচ্ছেন:

echo $VAR # strips newlines

echo "$VAR" # preserves newlines


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

11

নীলের উত্তরটি মুছে ফেলা , আপনার প্রায়শই কোনও ভারের প্রয়োজন হয় না, আপনি কোনও ফাংশনটি ভেরিয়েবলের মতো একই উপায়ে ব্যবহার করতে পারেন এবং ইনলাইন বা readভিত্তিক সমাধানগুলির চেয়ে এটি পড়া সহজ ।

$ complex_message() {
  cat <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF
}

$ echo "This is a $(complex_message)"
This is a abc'asdf"
$(dont-execute-this)
foo"bar"''

9

একটি অ্যারে একটি পরিবর্তনশীল, সুতরাং সেই ক্ষেত্রে ম্যাপফাইলে কাজ করবে

mapfile y <<z
abc'asdf"
$(dont-execute-this)
foo"bar"''
z

তারপরে আপনি এটি মুদ্রণ করতে পারেন

printf %s "${y[@]}"

3

একটি ভেরিয়েবলের জন্য একটি বংশগত মান নির্ধারণ করুন

VAR="$(cat <<'VAREOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
VAREOF
)"

একটি কমান্ডের আর্গুমেন্ট হিসাবে ব্যবহৃত

echo "$(cat <<'SQLEOF'
xxx''xxx'xxx'xx  123123    123123
abc'asdf"
$(dont-execute-this)
foo"bar"''
SQLEOF
)"

যখন আমি প্রথম পদ্ধতিটি চেষ্টা করেছি তখন মনে হয় রেখার মধ্যে কোনও লাইন টার্মিনেটর নেই। আমার লিনাক্স মেশিনে কোনও ধরণের কনফিগারেশন থাকতে হবে?
কেমিন চিউ

এর অর্থ সম্ভবত যখন আপনি আপনার পরিবর্তনশীল প্রতিধ্বনিত হতেন, আপনি চারপাশে উদ্ধৃতি রাখেন নি ... এটির মতো চেষ্টা করুন:echo "$VAR"
ব্র্যাড পার্কস

1

আমি এতে নিজেকে নুলের সাথে একটি স্ট্রিং পড়তে দেখেছি, সুতরাং এখানে এমন একটি সমাধান রয়েছে যা আপনি এতে যে কোনও কিছু পড়বেন তা পড়বে । যদিও আপনি যদি সত্যিই NULL এর সাথে ডিল করছেন তবে আপনাকে হেক্স পর্যায়ে এটি মোকাবেলা করতে হবে।

$ বিড়াল> read.dd.sh

read.dd() {
     buf= 
     while read; do
        buf+=$REPLY
     done < <( dd bs=1 2>/dev/null | xxd -p )

     printf -v REPLY '%b' $( sed 's/../ \\\x&/g' <<< $buf )
}

প্রমাণ:

$ . read.dd.sh
$ read.dd < read.dd.sh
$ echo -n "$REPLY" > read.dd.sh.copy
$ diff read.dd.sh read.dd.sh.copy || echo "File are different"
$ 

হারডোক উদাহরণ ((জে, ^ এম, ^ আই সহ):

$ read.dd <<'HEREDOC'
>       (TAB)
>       (SPACES)
(^J)^M(^M)
> DONE
>
> HEREDOC

$ declare -p REPLY
declare -- REPLY="  (TAB)
      (SPACES)
(^M)
DONE

"

$ declare -p REPLY | xxd
0000000: 6465 636c 6172 6520 2d2d 2052 4550 4c59  declare -- REPLY
0000010: 3d22 0928 5441 4229 0a20 2020 2020 2028  =".(TAB).      (
0000020: 5350 4143 4553 290a 285e 4a29 0d28 5e4d  SPACES).(^J).(^M
0000030: 290a 444f 4e45 0a0a 220a                 ).DONE

0

ডিমো 414 এর উত্তরের জন্য ধন্যবাদ , এটি তার দুর্দান্ত সমাধানটি কীভাবে কাজ করে তা দেখায় এবং দেখায় যে আপনি সহজেই টেক্সটে উদ্ধৃতি এবং ভেরিয়েবলগুলি রাখতে পারেন:

উদাহরণ আউটপুট

$ ./test.sh

The text from the example function is:
  Welcome dev: Would you "like" to know how many 'files' there are in /tmp?

  There are "      38" files in /tmp, according to the "wc" command

test.sh

#!/bin/bash

function text1()
{
  COUNT=$(\ls /tmp | wc -l)
cat <<EOF

  $1 Would you "like" to know how many 'files' there are in /tmp?

  There are "$COUNT" files in /tmp, according to the "wc" command

EOF
}

function main()
{
  OUT=$(text1 "Welcome dev:")
  echo "The text from the example function is: $OUT"
}

main

এটি কীভাবে পরিচালনা করে তা দেখতে পাঠ্যের কোনও তুলনামূলক উক্তিটি আকর্ষণীয় হবে। হতে পারে fre ফ্রিক আউট করবেন না, "" COUNT "ফাইল রয়েছে` যাতে অ্যাডাস্ট্রোফ / একক উদ্ধৃতি জিনিসগুলিকে আকর্ষণীয় করে তুলতে পারে।
ড্রাগন 788

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