হেরডোক (ইওএফ) এ ইকো-এন এর মতো কিছু আছে কি?


12

আমি আমার সার্ভারগুলির জন্য রক্ষণাবেক্ষণের প্রচুর স্ক্রিপ্ট তৈরি করে একটি বিশাল স্ক্রিপ্ট-কারখানা স্ক্রিপ্টে লিখছি।

এখন অবধি আমি কিছু লাইন লিখি যা echo -neউদাহরণস্বরূপ এক লাইনে লেখা দরকার

echo -n "if (( " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null

# Generate exitCode check for each Server
IFS=" "
COUNT=0
while read -r name ipAddr
do
    if(($COUNT != 0))
    then
        echo -n " || " | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
    fi

    echo -n "(\$"$name"_E != 0 && \$"$name"_E != 1)" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null

    COUNT=$((COUNT+1))

    JOBSDONE=$((JOBSDONE+1))
    updateProgress $JOBCOUNT $JOBSDONE
done <<< "$(sudo cat /root/.virtualMachines)"

echo " ))" | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null

এটি আমাকে উত্পন্ন করে (যদি আমার কনফিগ ফাইলে যেমন 2 টি সার্ভার থাকে) কোড পছন্দ করে like

if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))

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

cat << EOF | sudo tee -a /usr/local/bin/upgradeAllServers &> /dev/null
then
    # Print out ExitCode legend
    echo " ExitCode 42 - upgrade failed"
    echo " ExitCode 43 - Upgrade failed"
    echo " ExitCode 44 - Dist-Upgrade failed"
    echo " ExitCode 45 - Autoremove failed"
    echo ""
    echo ""
fi
EOF

চূড়ান্ত কোড ব্লকের মত দেখতে

if (( ($server1_E != 0 && $server1_E != 1) || ($server2_E != 0 && $server2_E != 1) ))
then
    # Print out ExitCode legend
    echo " ExitCode 42 - upgrade failed"
    echo " ExitCode 43 - Upgrade failed"
    echo " ExitCode 44 - Dist-Upgrade failed"
    echo " ExitCode 45 - Autoremove failed"
    echo ""
    echo ""
fi

আমার প্রশ্ন লাইন-প্রতীক শেষ
না echo -neকরেই কি কোনও উপায় হেরডোকের মতো আচরণ করে ?


1
আপনার যদি sudoকোনও স্ক্রিপ্টের প্রয়োজন হয় আপনি এটি ভুল করছেন: পরিবর্তে পুরো স্ক্রিপ্টটি রুট হিসাবে চালান!
মিষ্টান্ন

1
না কারণ এটি অন্যান্য
স্টাফগুলিও


আমি যেমন করে যাচ্ছি তাতে সমস্যা কি?
derHugo

4
অবশ্যই সমস্যা আছে: sudoব্যবহারকারীর নাম ছাড়াই একটি স্ক্রিপ্ট পাসওয়ার্ডের জন্য জিজ্ঞাসা করে, যদি না আপনি টাইপ না করেন তবে দেরি হয় না। এটি আরও খারাপ যদি আপনি কোনও টার্মিনালে স্ক্রিপ্টটি চালনা না করেন তবে আপনি পাসওয়ার্ড কোয়েরিও দেখতে পাবেন না এবং এটি কোনও কাজ করবে না। sudo -uপদ্ধতির এই সমস্যার কোন নেই।
মিষ্টান্ন

উত্তর:


9

না, হেরডোক সর্বদা একটি নতুন লাইনে শেষ হয়। তবে আপনি এখনও সর্বশেষ নিউলাইনটি সরাতে পারেন, উদাহরণস্বরূপ পার্ল সহ:

cat << 'EOF' | perl -pe 'chomp if eof'
First line
Second line
EOF
  • -pলাইন দ্বারা ইনপুট লাইন পড়ে, নির্দিষ্ট কোড চালায় -eএবং (সম্ভবত পরিবর্তিত) লাইনটি মুদ্রণ করে
  • chomp চূড়ান্ত নিউলাইনটি উপস্থিত থাকলে এটি সরিয়ে দেয়, eof ফাইলের শেষে সত্য ফিরে আসে।

1
@Yaron যদি প্রতি (এই ক্ষেত্রে বদ্ধ পাইপে) শেষ অফ ফাইল সম্মুখীন এটা সম্পর্কে newline গৃহস্থালির কাজ শেষ লাইন থেকে chomp হবে (যা কি heredoc এবং herestring অ্যাড স্বয়ংক্রিয়ভাবে)
Sergiy Kolodyazhnyy

7

শেষের দিকে লাইন-চিহ্ন ছাড়া ইকো-এন-এর অনুরূপ আচরণের মতো কোনও আচরণ আছে কি?

সংক্ষিপ্ত উত্তর হ'ল হেরডোক এবং হিস্ট্রোস্ট্রিংগুলি কেবল সেভাবেই নির্মিত হয়েছে , তাই না - এখানে - ডক এবং ইস্ট্রস্ট্রিং সর্বদা একটি পেছনের নতুন লাইন যুক্ত করবে এবং এটি অক্ষম করার কোনও বিকল্প বা দেশীয় উপায় নেই (সম্ভবত ভবিষ্যতে বাশ রিলিজ থাকবে?)।

তবে বাশ-কেবলমাত্র উপায়গুলির মাধ্যমে এটির কাছে যাওয়ার এক উপায় হ'ল হেরডোক স্ট্যান্ডার্ড while IFS= read -rপদ্ধতির মাধ্যমে কী দেয় তা পড়তে হবে , তবে একটি বিলম্ব সংযোজন করুন এবং শেষের লাইনটি printfপ্রচ্ছন্ন নিউলাইন ছাড়াই মুদ্রণ করুন । কেবল ব্যাশ-এর ​​মাধ্যমে কেউ কী করতে পারে তা এখানে:

#!/usr/bin/env bash

while true
do
    IFS= read -r line || { printf "%s" "$delayed";break;}
    if [ -n "$delayed" ]; 
    then
        printf "%s\n" "$delayed"
    fi
    delayed=$line
done <<EOF
one
two
EOF

আপনি এখানে যা দেখছেন তা স্বাভাবিক যখন IFS= read -r lineপদ্ধতির সাথে লুপ হয় তবে প্রতিটি লাইনটি একটি ভেরিয়েবলের মধ্যে সংরক্ষণ করা হয় এবং এভাবে বিলম্বিত হয় (সুতরাং আমরা প্রথম লাইনটি মুদ্রণ এড়িয়ে চলেছি, এটি সংরক্ষণ করব এবং কেবলমাত্র দ্বিতীয় লাইনের পড়ার পরে মুদ্রণ শুরু করব)। এইভাবে আমরা শেষ লাইনটি ক্যাপচার করতে পারি এবং পরবর্তী পুনরাবৃত্তির সময় যখন readপ্রস্থান স্থিতি 1 ফিরে আসে, তখনই আমরা নিউলাইন ছাড়াই শেষ লাইনটি প্রিন্ট করি printf। ভার্বোস? হ্যাঁ. কিন্তু এটি কাজ করে:

$ ./strip_heredoc_newline.sh                                      
one
two$ 

$কোনও নতুন লাইন নেই বলে প্রম্পট চরিত্রটিকে এগিয়ে দেওয়া হচ্ছে Notice একটি বোনাস হিসাবে, এই সমাধান তাই এটি কাজ করা উচিত পোর্টেবল এবং POSIX পর হয়, kshএবং dashহিসাবে ভাল।

$ dash ./strip_heredoc_newline.sh                                 
one
two$

6

আমি আপনাকে আলাদা পদ্ধতির চেষ্টা করার পরামর্শ দিচ্ছি। একাধিক প্রতিধ্বনি বিবৃতি এবং হেরডোকগুলি থেকে আপনার উত্পন্ন স্ক্রিপ্ট একসাথে পাইক করার পরিবর্তে। আমি আপনাকে একটি একক বংশধর ব্যবহার করার চেষ্টা করার পরামর্শ দিচ্ছি।

আপনি একটি বংশগতির ভিতরে পরিবর্তনশীল প্রসারণ এবং কমান্ড প্রতিস্থাপন ব্যবহার করতে পারেন। এই উদাহরণে পছন্দ করুন:

#!/bin/bash
cat <<EOF
$USER $(uname)
EOF

আমি দেখতে পাই যে এটি প্রায়শই টুকরো টুকরো করে আউটপুট টুকরো উত্পাদন করার চেয়ে অনেক বেশি পঠনযোগ্য ফলাফলের দিকে নিয়ে যায়।

এছাড়াও দেখে মনে হচ্ছে আপনি #!আপনার স্ক্রিপ্টগুলির শুরুতে লাইনটি ভুলে যাচ্ছেন । #!লাইন কোন সঠিক ফর্ম্যাটে স্ক্রিপ্ট-এ বাধ্যতামূলক। #!লাইনটি ছাড়া স্ক্রিপ্ট চালানোর চেষ্টা কেবলমাত্র তখনই কাজ করবে যদি আপনি এটি কোনও শেল থেকে কল করেন যা খারাপভাবে ফর্ম্যাট করা স্ক্রিপ্টগুলির চারপাশে কাজ করে এবং এমন ক্ষেত্রেও এটি আপনার উদ্দেশ্য থেকে আলাদা শেল দ্বারা ব্যাখ্যা করা শেষ হতে পারে।


ভুলে গেছেন #!তবে আমার কোড ব্লকটি 2000 লাইনের স্ক্রিপ্টের মধ্যে কেবল একটি স্নিপেট;) আমি এখনই দেখতে পাচ্ছি না যে আপনার পরামর্শটি কীভাবে লুপের মধ্যে একটি লাইন কোডের উত্পন্ন করার সমস্যাটি সমাধান করে ...
derHugo

লডার যেখানে আপনার লুপ দরকার সেই অংশটির @ @ হুগো কমান্ড প্রতিস্থাপন হ'ল এটি করার এক উপায়। আর একটি উপায় হেরডোকের আগে সেই অংশটি একটি ভেরিয়েবলে তৈরি করা। দুটির মধ্যে কোনটি সর্বাধিক পঠনযোগ্য তা নির্ভর করে লুপে প্রয়োজনীয় কোডের দৈর্ঘ্যের পাশাপাশি প্রশ্নে রেখার আগে আপনার কতটা হেরডোকের রেখা রয়েছে depends
কাস্পারড

@ ওডারহাগো কমান্ডের বিকল্পটি স্ক্রিপ্টের পূর্বনির্ধারিত শেল ফাংশনটির অনুরোধ করা একটি তৃতীয় পদ্ধতি যা আপনার যদি একটি লাইন তৈরির জন্য উল্লেখযোগ্য পরিমাণের কোডের প্রয়োজন হয় তবে এটি আরও পঠনযোগ্য হতে পারে।
ক্যাস্পারড

@ ওডারহুগো: দ্রষ্টব্য: (1) আপনার কাছে একটি লুপ থাকতে পারে যা সমস্ত প্রয়োজনীয় কমান্ডকে ভেরিয়েবলের মধ্যে রাখে; (২) আপনি $( ...command...)হেরেডোকের অভ্যন্তরে এই কমান্ডগুলির আউটপুট প্রবেশ করতে হেরেডোকের ভিতরে ব্যবহার করতে পারেন ; (3) বাশের অ্যারে ভেরিয়েবল রয়েছে, যা আপনি ইনলাইন প্রসারিত করতে পারেন, এবং প্রয়োজনে শুরুতে / শেষে জিনিসগুলি যুক্ত করতে বিকল্প ব্যবহার করুন। এগুলি একসাথে ক্যাস্পার্ডের পরামর্শকে আরও শক্তিশালী করে তোলে (এবং আপনার স্ক্রিপ্টটি সম্ভবত আরও অনেক বেশি পাঠযোগ্য)।
স্মারক

আমি হেরাদোকগুলি তাদের ধরণের টেম্পলেট আচরণের কারণে ব্যবহার করছি (ওয়াইসিউইগ)। পুরো টেমপ্লেটটিকে অন্য জায়গায় উত্পাদন করা এবং আমার মতে এটি হেরেডোকের কাছে পৌঁছে দেওয়ার চেয়ে বিষয়গুলি পড়া / বজায় রাখা সত্যিই সহজ করে না।
derHugo

2

বংশগতি সর্বদা একটি নতুন লাইন বর্ণগুলিতে শেষ হয় তবে আপনি এটিকে সরাতে পারেন। আমি জানি সবচেয়ে সহজ উপায় হল headপ্রোগ্রামটির সাথে:

head -c -1 <<EOF | sudo tee file > /dev/null
my
heredoc
content
EOF

কুল আমি জানি না যে -cনেতিবাচক মানও লাগে! pearlসমাধানের
derHugo

1

আপনি যেভাবে চান নিউলাইনগুলি সরিয়ে ফেলতে পারবেন, পাইপিং trসম্ভবত সহজ হবে। এটি অবশ্যই সমস্ত নিউলাইনগুলি সরিয়ে ফেলবে।

$ tr -d '\n' <<EOF 
if ((
EOF

তবে, যদি আপনি তৈরি করছেন এমন বিবৃতিটির প্রয়োজন হয় না, পাটিগণিতের এক্সপ্রেশনটি (( .. ))নতুন লাইনে থাকা সত্ত্বেও ঠিকঠাক কাজ করা উচিত।

সুতরাং, আপনি করতে পারে

cat <<EOF 
if ((
EOF
for name in x y; do 
    cat << EOF
    ( \$${name}_E != 0 && \$${name}_E != 1 ) ||
EOF
done
cat <<EOF
    0 )) ; then 
    echo do something
fi
EOF

আবহ

if ((
    ( $x_E != 0 && $x_E != 1 ) ||
    ( $y_E != 0 && $y_E != 1 ) ||
    0 )) ; then 
    echo do something
fi

এটি একটি লুপে তৈরি করা এখনও কুশ্রী করে তোলে। || 0আমরা বিশেষ ক্ষেত্রে প্রথম অথবা শেষ লাইন প্রয়োজন হবে না অবশ্যই এত নেই।


এছাড়াও, আপনি | sudo tee ...প্রতিটি আউটপুট এ আছে। আমি মনে করি আমরা কেবল একবার (পুনরায় প্রক্রিয়া বিকল্প সহ) পুনঃনির্দেশটি খোলার মাধ্যমে এবং পরের মুদ্রণের জন্য এটি ব্যবহার করে মুক্তি থেকে মুক্তি পেতে পারি:

exec 3> >(sudo tee outputfile &>/dev/null)
echo output to the pipe like this >&3
echo etc. >&3
exec 3>&-         # close it in the end

এবং প্রকৃতপক্ষে, আমি এখনও মনে করি যে বাইরের স্ক্রিপ্টে ভেরিয়েবলের থেকে ভেরিয়েবলের নাম তৈরি করা (এর মতো \$${name}_E) কিছুটা কুৎসিত, এবং সম্ভবত এটি একটি মিশুক অ্যারের সাথে প্রতিস্থাপন করা উচিত ।

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