বাশ বা zsh এ শেল ভেরিয়েবল সিরিয়ালাইজ করুন


12

শেল ভেরিয়েবলকে সিরিয়াল করার কোনও উপায় আছে কি? মনে করুন আমার একটি পরিবর্তনশীল আছে $VAR, এবং আমি এটি কোনও ফাইল বা যে কোনও কিছুতে সংরক্ষণ করতে সক্ষম হতে চাই এবং তার পরে একই মানটি ফিরে পেতে আবার পড়তে পারি?

এটি করার কোনও পোর্টেবল উপায় আছে? (আমি তাই মনে করি না)

বাশ বা zsh এ এটি করার কোনও উপায় আছে?


2
মনোযোগ দিন: আপনি যে দিন আমার উত্তরের সংস্করণটি গ্রহণ করেছেন সেটিতে একটি গুরুতর সমস্যা ছিল যা কিছু পরিস্থিতিতে ভেঙে যাবে। আমি ফিক্সগুলি অন্তর্ভুক্ত করার জন্য এটি পুনরায় লিখেছি (এবং বৈশিষ্ট্যগুলি যোগ করুন) এবং আপনার সত্যিকারের এটি পুনরায় পড়তে হবে এবং স্থির সংস্করণটি ব্যবহার করার জন্য আপনার কোডটি পোর্ট করা উচিত।
কালেব

@ কালেবের উঁচু নাগরিকত্বের আরও একটি উদাহরণ ^
মাইকসার্ভ

উত্তর:


14

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

এক বা একাধিক ভেরিয়েবল সিরিয়াল করার জন্য সহজ ইনলাইন প্রয়োগ implementation

হ্যাঁ, ব্যাশ এবং জ্যাশ উভয় ক্ষেত্রেই আপনি কোনও ভেরিয়েবলের বিষয়বস্তু এমনভাবে সিরিয়ালাইজ করতে পারেন যা typesetবিল্টিন এবং -pযুক্তি ব্যবহার করে পুনরুদ্ধার করা সহজ । আউটপুট বিন্যাসটি এমন যে আপনি sourceনিজের জিনিসগুলি ফিরে পেতে কেবল আউটপুট নিতে পারেন।

 # You have variable(s) $FOO and $BAR already with your stuff
 typeset -p FOO BAR > ./serialized_data.sh

আপনি আপনার জিনিসগুলি আবার আপনার স্ক্রিপ্টে বা অন্য স্ক্রিপ্টে পুরোপুরি ফিরে পেতে পারেন:

# Load up the serialized data back into the current shell
source serialized_data.sh

এটি বিভিন্ন শেলের মধ্যে ডেটা পাশ করার সাথে সাথে ব্যাশ, জেডএস এবং কেএস এর জন্য কাজ করবে। বাশ তার বিল্টিন declareফাংশনটিতে এটি অনুবাদ করবে যখন zsh এটি প্রয়োগ করে তবে কেএসএসের সামঞ্জস্যের typesetজন্য আমরা typesetএখানে যেভাবেই ব্যবহার করি তার জন্য ব্যাশের একটি উপাধ রয়েছে।

ফাংশন ব্যবহার করে আরও জটিল সাধারণীকরণের বাস্তবায়ন

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

এগুলির জন্য নোট করুন, ব্যাশ / জেডএস ক্রস-সামঞ্জস্যতা বজায় রাখার জন্য আমরা উভয় ক্ষেত্রেই ঠিক করব typesetএবং declareসুতরাং কোডটি উভয় শেলের মধ্যে কাজ করা উচিত। এটি কিছু বাল্ক এবং গণ্ডগোল যোগ করে যা আপনি যদি কেবলমাত্র একটি শেল বা অন্য একটির জন্য এটি করে থাকেন তবে তা মুছে ফেলা হতে পারে।

এর জন্য ফাংশনগুলি ব্যবহার করার (বা অন্যান্য ফাংশনের কোড সহ) প্রধান সমস্যাটি হ'ল typesetফাংশনটি এমন একটি কোড উত্পন্ন করে যা কোনও ফাংশনের অভ্যন্তর থেকে কোনও স্ক্রিপ্টে ফিরিয়ে নেওয়া হলে গ্লোবালটির পরিবর্তে স্থানীয় পরিবর্তনশীল তৈরিতে ডিফল্ট হয়।

এটি বেশ কয়েকটি হ্যাকের একটিতে স্থির করা যেতে পারে। এটি ঠিক করার জন্য আমার প্রাথমিক প্রয়াসটি পতাকা sedযোগ করার জন্য সিরিয়ালাইজ প্রক্রিয়াটির আউটপুটকে পার্স করা হয়েছিল -gযাতে তৈরি কোডটি যখন স্রোসিত হয় তখন গ্লোবাল ভেরিয়েবলকে সংজ্ঞায়িত করে।

serialize() {
    typeset -p "$1" | sed -E '0,/^(typeset|declare)/{s/ / -g /}' > "./serialized_$1.sh"
}
deserialize() {
    source "./serialized_$1.sh"
}

নোট করুন যে ফানসি sedএক্সপ্রেশনটি কেবল 'টাইপসেট' বা 'ডিক্লেয়ার' এর প্রথম ঘটনার সাথে মেলে এবং -gপ্রথম যুক্তি হিসাবে যুক্ত করা। এটি কেবলমাত্র প্রথম ঘটনার সাথেই মিলিত হওয়া প্রয়োজন কারণ স্টাফেন চাজেলাস যথাযথভাবে মন্তব্যে উল্লেখ করেছেন, অন্যথায় এটি এমন ক্ষেত্রেও মিলবে যেখানে সিরিয়ালযুক্ত স্ট্রিংয়ে ডিক্লার বা টাইপসেট শব্দের পরে আক্ষরিক নিউলাইন রয়েছে।

আমার প্রাথমিক পার্সিংয়ের ভুল পার্সকে সংশোধন করার পাশাপাশি স্টাফেন এটি হ্যাক করার জন্য একটি কম ভঙ্গুর উপায়ও বলেছিল যা কেবল স্ট্রিংগুলি পার্সিংয়ের সাথে সমস্যার সমাধান করে না তবে ক্রিয়াগুলি নতুন করে সংজ্ঞায়িত করার জন্য একটি মোড়ক ফাংশন ব্যবহার করে অতিরিক্ত কার্যকারিতা যুক্ত করার জন্য দরকারী হুক হতে পারে ডেটা ফেরত দেওয়ার সময় নেওয়া হয়েছিল This এটি ধরে নেওয়া হয় আপনি ঘোষিত বা টাইপসেট আদেশগুলি দিয়ে অন্য কোনও গেম খেলছেন না, তবে এই কৌশলটি আপনার নিজের বা অন্য কোনও ক্রিয়াকলাপের অংশ হিসাবে আপনি যখন এই কার্যকারিতাটি অন্তর্ভুক্ত করেছিলেন এমন পরিস্থিতিতে কার্যকর করা সহজ হবে or আপনি ডেটা লিখিত হচ্ছে এবং -gপতাকাটি যুক্ত হয়েছে কিনা তা আপনার নিয়ন্ত্রণে ছিল না । অনুরূপ কিছু উপকরণের সাথেও করা যেতে পারে, বাস্তবায়নের জন্য গিলসের উত্তর দেখুন ।

ফলাফলটিকে আরও কার্যকর করতে আমরা আর্গুমেন্ট অ্যারের প্রতিটি শব্দ একটি ভেরিয়েবলের নাম ধরে ধরে আমাদের ফাংশনগুলিতে একাধিক ভেরিয়েবলগুলি পুনরুক্ত করতে পারি। ফলাফলটি এরকম কিছু হয়ে যায়:

serialize() {
    for var in $@; do
        typeset -p "$var" > "./serialized_$var.sh"
    done
}

deserialize() {
    declare() { builtin declare -g "$@"; }
    typeset() { builtin typeset -g "$@"; }
    for var in $@; do
        source "./serialized_$var.sh"
    done
    unset -f declare typeset
}

উভয় সমাধানের সাহায্যে ব্যবহারটি দেখতে এই রকম হবে:

# Load some test data into variables
FOO=(an array or something)
BAR=$(uptime)

# Save it out to our serialized data files
serialize FOO BAR

# For testing purposes unset the variables to we know if it worked
unset FOO BAR

# Load  the data back in from out data files
deserialize FOO BAR

echo "FOO: $FOO\nBAR: $BAR"

declareহয় bashসমতুল্য ksh'র typesetbash, zshএছাড়াও typesetসেই ক্ষেত্রে সমর্থন , typesetআরও বহনযোগ্য। export -pপসিক্স, তবে এটি কোনও যুক্তি গ্রহণ করে না এবং এর আউটপুটটি শেল নির্ভর (যদিও এটি পসিক্স শেলগুলির জন্য ভালভাবে নির্দিষ্ট করা হয়েছে, উদাহরণস্বরূপ যখন বাশ বা কেএস বলা হয় sh)। আপনার ভেরিয়েবল উদ্ধৃত মনে রাখবেন; এখানে বিভক্ত + গ্লোব অপারেটরটি ব্যবহার করার কোনও অর্থ নেই।
স্টাফেন চেজেলাস

নোট যেটি -Eশুধুমাত্র কিছু বিএসডি তে পাওয়া যায় sed। পরিবর্তনশীল মানগুলিতে নিউলাইন অক্ষর থাকতে পারে, সুতরাং এটি sed 's/^.../.../'সঠিকভাবে কাজ করার গ্যারান্টিযুক্ত নয়।
স্টাফেন চেজেলাস

আমি ঠিক এটিই খুঁজছিলাম! আমি শেলের মধ্যে ভেরিয়েবলগুলি পিছনে পিছনে ঠেলে দেওয়ার জন্য একটি সুবিধাজনক উপায় চেয়েছিলাম
fwenom

আমি বলতে চাইছিলাম: a=$'foo\ndeclare bar' bash -c 'declare -p a'ইনস্টলের জন্য একটি লাইন আউটপুট আসবে যা শুরু হয় declaredeclare() { builtin declare -g "$@"; }কল করার আগে সম্ভবত এটি করা ভাল source(এবং তারপরে সেট না করা)
স্টাফেন চেজেলাস

2
@ গিলিস, এলিয়াসগুলি ফাংশনের অভ্যন্তরে কাজ করবে না (ফাংশন সংজ্ঞা দেওয়ার সময় সংজ্ঞায়িত করা দরকার), এবং ব্যাশের সাথে বোঝা যাচ্ছে যে shopt -s expandaliasইন্টারেক্টিভ না হলে আপনাকে একটি কাজ করতে হবে । ফাংশনগুলির সাথে, আপনি declareমোড়কে বাড়িয়ে দিতে পারেন যাতে এটি কেবল আপনার নির্দিষ্ট করা পরিবর্তনগুলি পুনরুদ্ধার করে।
স্টাফেন চেজেলাস

3

পুনঃনির্দেশ, কমান্ড প্রতিস্থাপন এবং প্যারামিটার সম্প্রসারণ ব্যবহার করুন। সাদা স্থান এবং বিশেষ অক্ষর সংরক্ষণের জন্য ডাবল উদ্ধৃতি প্রয়োজন। চিহ্ন xtrailing নতুন লাইন যা অন্যথায় কমান্ড প্রতিকল্পন সরানো হবে পরিমাণ সঞ্চয় হয়।

#!/bin/bash
echo "$var"x > file
unset var
var="$(< file)"
var=${var%x}

তিনি সম্ভবত ভেরিয়েবলের নামটিও ফাইলটিতে সংরক্ষণ করতে চান।
ব্যবহারকারী 80551

2

সমস্ত ক্রমিক করুন - পসিক্স

যে কোনও পসিক্স শেলের মধ্যে আপনি সমস্ত পরিবেশ ভেরিয়েবলকে সিরিয়ালাইজ করতে পারেন export -p। এর মধ্যে অ-রপ্তানি শেল ভেরিয়েবলগুলি অন্তর্ভুক্ত নয়। আউটপুটটি সঠিকভাবে উদ্ধৃত হয়েছে যাতে আপনি এটি আবার একই শেলের মধ্যে পড়তে পারেন এবং ঠিক একই পরিবর্তনশীল মানগুলি পেতে পারেন। আউটপুট অন্য শেলের মধ্যে পঠনযোগ্য নাও হতে পারে, উদাহরণস্বরূপ ksh নন-পসিক্স $'…'সিনট্যাক্স ব্যবহার করে ।

save_environment () {
  export -p >my_environment
}
restore_environment () {
  . ./my_environment
}

কিছু বা সমস্ত ক্রমিক - ksh, বাশ, zsh

Ksh (উভয় pdksh / mksh এবং এটিটি ksh), বাশ এবং zsh বিল্টিনের সাথে আরও ভাল সুবিধা সরবরাহ করে typesettypeset -pসমস্ত সংজ্ঞায়িত ভেরিয়েবল এবং তাদের মানগুলি মুদ্রণ করে (zsh এর সাথে লুকানো ভেরিয়েবলের মান বাদ দেয় typeset -H)। আউটপুটে যথাযথ ঘোষণা রয়েছে যাতে পরিবেশের চলকগুলি পুনরায় পড়ার সময় রফতানি করা হয় (তবে যদি কোনও ভেরিয়েবল ইতিমধ্যে পুনরায় পড়ার সময় রফতানি করা হয় তবে এটি এক্সপোর্ট করা হবে না), যাতে অ্যারেগুলি অ্যারে ইত্যাদি হিসাবে পুনরায় পাঠানো হয় Here এখানেও আউটপুট যথাযথভাবে উদ্ধৃত হয়েছে তবে কেবল একই শেলের মধ্যে পড়ার গ্যারান্টিযুক্ত। কমান্ড লাইনে সিরিয়ালাইজ করতে আপনি ভেরিয়েবলের একটি সেট পাস করতে পারেন; আপনি যদি কোনও ভেরিয়েবল পাস না করেন তবে সমস্ত ক্রমিকায়িত হয়।

save_some_variables () {
  typeset -p VAR OTHER_VAR >some_vars
}

ব্যাশ এবং জ্যাশে, কোনও ফাংশন থেকে পুনরুদ্ধার করা যায় না কারণ typesetকোনও ফাংশনের অভ্যন্তরে বিবৃতিগুলি সেই ফাংশনে স্কোপ করে। . ./some_varsরফতানির সময় বিশ্বব্যাপী যে ভেরিয়েবলগুলি বিশ্বব্যাপী ঘোষিত হবে সেদিকে খেয়াল রেখে আপনি যেখানে সেই পরিবর্তনশীল মানগুলি ব্যবহার করতে চান সেই প্রসঙ্গে আপনাকে চালনা করতে হবে। যদি আপনি কোনও ফাংশনের মধ্যে মানগুলি আবার পড়তে চান এবং সেগুলি রফতানি করতে চান তবে আপনি একটি অস্থায়ী নাম বা ফাংশন ঘোষণা করতে পারেন। জেডএসে:

restore_and_make_all_global () {
  alias typeset='typeset -g'
  . ./some_vars
  unalias typeset
}

ব্যাশে (যা এর declareপরিবর্তে ব্যবহার করে typeset):

restore_and_make_all_global () {
  alias declare='declare -g'
  shopt -s expand_aliases
  . ./some_vars
  unalias declare
}

কেএসএসে, typesetসংজ্ঞায়িত ফাংশনগুলিতে স্থানীয় ভেরিয়েবল এবং সংজ্ঞাযুক্ত ফাংশনগুলিতে function function_name { … }গ্লোবাল ভেরিয়েবল ঘোষণা করে function_name () { … }

কিছু সিরিয়াল করুন - পসিক্স

আপনি যদি আরও নিয়ন্ত্রণ চান তবে আপনি নিজেই কোনও চলকের বিষয়বস্তু রফতানি করতে পারেন। কোনও ভেরিয়েবলের বিষয়বস্তু হুবহু ফাইলে মুদ্রণের জন্য, printfবিল্টিনটি ব্যবহার করুন ( echoকয়েকটি বিশেষ echo -nশেল যেমন কিছু শেল রয়েছে এবং একটি নতুন লাইন যুক্ত করেছেন):

printf %s "$VAR" >VAR.content

$(cat VAR.content)কমান্ড প্রতিস্থাপনটি নতুন লাইনের পিছনে পড়া বাদ দিয়ে আপনি এটিকে আবার পড়তে পারেন । এই কুঁচকে এড়াতে, আউটপুট কখনও কোনও নতুন লাইনের সাথে শেষ না হওয়ার ব্যবস্থা করুন।

VAR=$(cat VAR.content && echo a)
if [ $? -ne 0 ]; then echo 1>&2 "Error reading back VAR"; exit 2; fi
VAR=${VAR%?}

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

serialize_variables () {
  for __serialize_variables_x do
    eval "printf $__serialize_variables_x=\\'%s\\'\\\\n \"\$${__serialize_variables_x}\"" |
    sed -e "s/'/'\\\\''/g" -e '1 s/=.../=/' -e '$ s/...$//'
  done
}

এখানে অন্য পদ্ধতির যা একটি সাবপ্রসেস কাঁটা না কিন্তু স্ট্রিং ম্যানিপুলেশন উপর ভারী।

serialize_variables () {
  for __serialize_variables_var do
    eval "__serialize_variables_tail=\${$__serialize_variables_var}"
    while __serialize_variables_quoted="$__serialize_variables_quoted${__serialize_variables_tail%%\'*}"
          [ "${__serialize_variables_tail%%\'*}" != "$__serialize_variables_tail" ]; do
      __serialize_variables_tail="${__serialize_variables_tail#*\'}"
      __serialize_variables_quoted="${__serialize_variables_quoted}'\\''"
    done
    printf "$__serialize_variables_var='%s'\n" "$__serialize_variables_quoted"
  done
}

মনে রাখবেন যে শেলগুলিতে কেবল পঠনযোগ্য ভেরিয়েবলগুলিকে মঞ্জুরি দেয়, আপনি যদি কেবলমাত্র পঠনযোগ্য একটি ভেরিয়েবলটি পুনরায় পড়ার চেষ্টা করেন তবে আপনি একটি ত্রুটি পাবেন।


এটি যেমন ভেরিয়েবল নিয়ে আসে $PWDএবং $_- দয়া করে নীচে আপনার নিজের মন্তব্য দেখুন।
মাইক্রজারভ

@ কালেব কীভাবে typesetএকটি উপনাম তৈরি করবেন typeset -g?
গিলস'স'-এ খারাপ হওয়া বন্ধ করুন '

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

0

@ Stéphane-chazelas কে অনেক ধন্যবাদ যারা আমার আগের প্রচেষ্টাগুলির দ্বারা সমস্ত সমস্যা চিহ্নিত করেছেন, এটি এখন স্ট্রাউট বা ভেরিয়েবলের জন্য একটি অ্যারে সিরিয়াল হিসাবে কাজ করে বলে মনে হচ্ছে।

এই কৌশলটি ইনপুটটিকে শেল-পার্স করে না (বিপরীতে declare -a/ declare -p) এবং তাই সিরিয়ালীকৃত পাঠ্যে মেটাচার্যাক্টরের দূষিত সন্নিবেশ বিরুদ্ধে নিরাপদ।

দ্রষ্টব্য: নিউলাইনগুলি এড়ায় না, কারণ চরিত্রের জুটি readমুছে দেয় \<newlines>, সুতরাং -d ...পরিবর্তে পড়ার জন্য পাস করতে হবে এবং তারপরে অবিচ্ছিন্ন নিউলাইনগুলি সংরক্ষণ করা হবে।

এই সমস্ত unserialiseফাংশন পরিচালিত হয় ।

দুটি যাদু চরিত্র ব্যবহৃত হয়, ক্ষেত্র বিভাজক এবং রেকর্ড বিভাজক (যাতে একাধিক অ্যারে একই স্ট্রিমিতে সিরিয়ালাইজ করা যায়)।

এই অক্ষরগুলিকে হিসাবে সংজ্ঞায়িত করা যায় FSএবং RSতবে newlineচরিত্র হিসাবে সংজ্ঞায়িত করা যায় না কারণ একটি পালানো নিউলাইন দ্বারা মুছে ফেলা হয় read

পালানোর চরিত্রটি অবশ্যই \ব্যাকস্ল্যাশ হতে হবে , যেমনটি readচরিত্রটিকে একটি IFSচরিত্র হিসাবে স্বীকৃতি দেওয়া থেকে বাঁচতে ব্যবহৃত হয় ।

serialise"$@"stdout যাও সিরিয়াল হবে , serialise_toনাম পরিবর্তনশীল যাও সিরিয়াল হবে$1

serialise() {
  set -- "${@//\\/\\\\}" # \
  set -- "${@//${FS:-;}/\\${FS:-;}}" # ; - our field separator
  set -- "${@//${RS:-:}/\\${RS:-:}}" # ; - our record separator
  local IFS="${FS:-;}"
  printf ${SERIALIZE_TARGET:+-v"$SERIALIZE_TARGET"} "%s" "$*${RS:-:}"
}
serialise_to() {
  SERIALIZE_TARGET="$1" serialise "${@:2}"
}
unserialise() {
  local IFS="${FS:-;}"
  if test -n "$2"
  then read -d "${RS:-:}" -a "$1" <<<"${*:2}"
  else read -d "${RS:-:}" -a "$1"
  fi
}

এবং সাথে unserialise:

unserialise data # read from stdin

অথবা

unserialise data "$serialised_data" # from args

যেমন

$ serialise "Now is the time" "For all good men" "To drink \$drink" "At the \`party\`" $'Party\tParty\tParty'
Now is the time;For all good men;To drink $drink;At the `party`;Party   Party   Party:

(পেছনের নতুন লাইন ছাড়া)

এটি আবার পড়ুন:

$ serialise_to s "Now is the time" "For all good men" "To drink \$drink" "At the \`party\`" $'Party\tParty\tParty'
$ unserialise array "$s"
$ echo "${array[@]/#/$'\n'}"

Now is the time 
For all good men 
To drink $drink 
At the `party` 
Party   Party   Party

অথবা

unserialise array # read from stdin

ইনপুট ফিল্ড বিচ্ছিন্নতা বা লাইন সীমানাঙ্কিতের মতো অক্ষরের বিশেষ অর্থ সরাতে বাশের readপালানোর চরিত্রটিকে \(যদি আপনি -r পতাকাটি পাস না করেন) সম্মান করে ।

আপনি যদি কেবল একটি যুক্তি তালিকার পরিবর্তে একটি অ্যারে সিরিয়াল করতে চান তবে কেবল আপনার অ্যারেটিকে যুক্তি তালিকা হিসাবে পাস করুন:

serialise_array "${my_array[@]}"

আপনি unserialiseযেমন চান readতেমন একটি লুপ ব্যবহার করতে পারেন কারণ এটি কেবল একটি আবৃত পঠন - তবে মনে রাখবেন যে স্ট্রিমটি নতুন লাইনটি পৃথক নয়:

while unserialise array
do ...
done

উপাদানগুলিতে মুদ্রণযোগ্য (বর্তমান লোকালে) বা ত্যাব বা নিউলাইনের মতো অক্ষরগুলি নিয়ন্ত্রণ করে bashএবং zshসেগুলি হিসাবে রেন্ডার করা থাকলে এটি কার্যকর হয় না $'\xxx'bash -c $'printf "%q\n" "\t"'বা দিয়ে চেষ্টা করুনbash -c $'printf "%q\n" "\u0378"'
স্টাফেন চ্যাজেলাস

টরটিন ডার্ন, আপনি ঠিক বলেছেন! আমি
মুদ্রণ

এই সমাধানটি $IFSসংশোধিত হওয়ার উপর নির্ভর করে এবং এখন খালি অ্যারে উপাদানগুলি সঠিকভাবে পুনরুদ্ধার করতে ব্যর্থ। প্রকৃতপক্ষে, আইএফএসের আলাদা মানটি ব্যবহার করা আরও বেশি অর্থবোধ করে এবং -d ''নিউলাইন থেকে বাঁচতে না পারা ব্যবহার করে। উদাহরণস্বরূপ, :ফিল্ড বিভাজক হিসাবে ব্যবহার করুন এবং কেবলমাত্র এটি এবং ব্যাকস্ল্যাশ এড়িয়ে চলুন এবং IFS=: read -ad '' arrayআমদানির জন্য ব্যবহার করুন।
স্টাফেন শেজেলাস

হ্যাঁ .... পড়ার ক্ষেত্রে ক্ষেত্র বিভাজক হিসাবে ব্যবহার করার সময় আমি সাদা-স্পেসের ক্র্যাশিং বিশেষ চিকিত্সা সম্পর্কে ভুলে গিয়েছিলাম। আমি খুশি যে আপনি আজ বলের উপর! আপনি "escap n" রক্ষা পেতে এড়াতে ঠিক বলেছেন, তবে আমার ক্ষেত্রে আমি ধারাবাহিকতার একটি ধারা পড়তে চেয়েছিলাম - যদিও আমি উত্তরটি মানিয়ে নেব। ধন্যবাদ!
স্যাম লিডিকোট

নতুন লাইন ছেড়ে যাওয়া এটিকে সংরক্ষণ করার অনুমতি দেয় না, এটি একবারে চলে যায় read। এর জন্য ব্যাকস্ল্যাশ-নিউলাইন readহ'ল অন্য শারীরিক লাইনে লজিকাল লাইন চালিয়ে যাওয়ার উপায়। সম্পাদনা: আহ আমি দেখছি আপনি ইতিমধ্যে নতুন লাইনের সাথে সমস্যার উল্লেখ করেছেন।
স্টাফেন চেজেলাস

0

আপনি ব্যবহার করতে পারেন base64:

$ VAR="1/ 
,x"
$ echo "$VAR" | base64 > f
$ VAR=$(cat f | base64 -d)
$ echo "${VAR}X"
1/ 
,xX

-2
printf 'VAR=$(cat <<\'$$VAR$$'\n%s\n'$$VAR$$'\n)' "$VAR" >./VAR.file

এটি করার আরেকটি উপায় হ'ল আপনি 'এই জাতীয় সমস্ত হার্ডকোটকে পরিচালনা করছেন তা নিশ্চিত করা :

sed '"s/'"'/&"&"&/g;H;1h;$!d;g;'"s/.*/VAR='&'/" <<$$VAR$$ >./VAR.file
$VAR
$$VAR$$

বা সাথে export:

env - "VAR=$VAR" sh -c 'export -p' >./VAR.file 

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

"\n${CURRENT_SHELLS_PID}VAR${CURRENT_SHELLS_PID}\n" 

তৃতীয় বিকল্পটি কোনও পসিক্স শেলের জন্য কাজ করা উচিত তবে অন্যান্য ভেরিয়েবলগুলি যেমন _বা হিসাবে সংজ্ঞায়নের চেষ্টা করতে পারে PWD। যদিও সত্য, এটি নির্ধারণ করতে পারে এমন একমাত্র পরিবর্তনশীলগুলি নিজেই শেল দ্বারা সেট এবং রক্ষণাবেক্ষণ করা হয় - এবং এরপরেও যদি আপনি তাদের কারওর exportজন্য আমদানির মান করেন - যেমন $PWD- শেলটি কেবল এগুলিতে পুনরায় সেট করবে তত্ক্ষণাতই সঠিক মান - নিজের চেষ্টা করে PWD=any_valueদেখুন for

এবং কারণ - কমপক্ষে GNU এর সাথে bash- ডিবেগ আউটপুট শেলটিতে পুনরায় ইনপুট দেওয়ার জন্য স্বয়ংক্রিয়ভাবে নিরাপদে উদ্ধৃত হয়, এতে 'হার্ড-কোট সংখ্যা নির্বিশেষে এটি কাজ করে "$VAR":

 PS4= VAR=$VAR sh -cx 'VAR=$VAR' 2>./VAR.file

$VAR নিম্নলিখিত স্ক্রিনে নিম্নলিখিত পথটি বৈধ যেখানে কোনও স্ক্রিপ্টে সংরক্ষিত মানকে পরে সেট করা যেতে পারে:

. ./VAR.file

আমি নিশ্চিত না যে আপনি প্রথম কমান্ডে কী লেখার চেষ্টা করেছিলেন। $$চলমান শেলের পিআইডি, আপনি কি উদ্ধৃতিটি ভুল এবং মানে \$বা কিছু পেয়েছেন? এখানে ডকুমেন্টটি ব্যবহারের প্রাথমিক পদ্ধতির কাজটি করা যেতে পারে তবে এটি মুশকিল, ওয়ান-লাইনার উপাদান নয়: আপনি শেষের চিহ্ন হিসাবে যা কিছু বেছে নিন না কেন আপনাকে এমন কিছু বাছাই করতে হবে যা স্ট্রিংয়ে প্রদর্শিত না হয়।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

$VARথাকে যখন দ্বিতীয় কমান্ড কাজ করে না %। তৃতীয় কমান্ড সর্বদা একাধিক লাইন সম্বলিত মানগুলির সাথে কাজ করে না (স্পষ্টত অনুপস্থিত ডাবল উদ্ধৃতি যুক্ত করার পরেও)।
গিলস 23'17

@ গিলস - আমি এর পিড জানি - আমি এটি একটি অনন্য সীমানা নির্ধারণের সাধারণ উত্স হিসাবে ব্যবহার করেছি। "সর্বদা না" বলতে আপনার অর্থ কী? এবং আমি বুঝতে পারছি না ডাবল উদ্ধৃতিগুলি কী অনুপস্থিত - সেগুলি সবই ভেরিয়েবল অ্যাসাইনমেন্ট। ডাবল উদ্ধৃতি কেবল সেই প্রসঙ্গে পরিস্থিতিকে বিভ্রান্ত করে।
মাইকজার্ভ

@ গিলস - আমি অ্যাসাইনমেন্ট জিনিসটি প্রত্যাহার করি - এটি একটি তর্ক env। আমি একাধিক লাইন সম্পর্কে কী বোঝাতে চাইছি তা এখনও আগ্রহী - শেষ sedঅবধি দেখা VAR=না হওয়া পর্যন্ত প্রতিটি লাইন মুছে ফেলে - তাই সমস্ত লাইনই $VARপেরিয়ে যায়। আপনি দয়া করে একটি উদাহরণ প্রদান করতে পারেন যা এটি ভেঙে দেয়?
মাইকসার্ভ

আহ, দুঃখিত, তৃতীয় পদ্ধতিটি কাজ করে (উদ্ধৃতি সংশোধন সহ)। ঠিক আছে, ভেরিয়েবলের নাম (এখানে VAR) পরিবর্তন করা হয় নি PWDবা _কিছু শেল সংজ্ঞায়িত করে এমন অন্য কেউ সম্ভবত। দ্বিতীয় পদ্ধতিতে বাশ প্রয়োজন; থেকে আউটপুট ফর্ম্যাট -vমানকৃত নয় (কোনও ড্যাশ, কেএস 93, ম্যাক্স এবং জেডশিয়ার কাজের নয়)।
গিলস 'অশুভ হওয়া বন্ধ করুন'

-2

প্রায় একই তবে কিছুটা আলাদা:

আপনার স্ক্রিপ্ট থেকে:

#!/usr/bin/ksh 

save_var()
{

    (for ITEM in $*
    do
        LVALUE='${'${ITEM}'}'
        eval RVALUE="$LVALUE"
        echo "$ITEM=\"$RVALUE\""  
    done) >> $cfg_file
}

restore_vars()
{
    . $cfg_file
}

cfg_file=config_file
MY_VAR1="Test value 1"
MY_VAR2="Test 
value 2"

save_var MY_VAR1 MY_VAR2
MY_VAR1=""
MY_VAR2=""

restore_vars 

echo "$MY_VAR1"
echo "$MY_VAR2"

এই সময় উপরে পরীক্ষা করা হয়।


আমি দেখতে পাচ্ছি আপনি পরীক্ষা করেননি! মূল যুক্তি কাজ করে, তবে এটি কিছুটা কঠিন নয়। কঠিন কিছু জিনিসকে সঠিকভাবে উদ্ধৃত করা হচ্ছে, এবং আপনি এর কোনও কাজ করছেন না। ভেরিয়েবল যার মান নতুন লাইন ধারণ করে দেখুন ', *ইত্যাদি
গিলেজ 'SO- মন্দ থামাতে হল' ''

echo "$LVALUE=\"$RVALUE\""নতুন লাইনের পাশাপাশি রাখার কথা রয়েছে এবং সিএফজি_ফাইলে ফলাফলটি এমন হওয়া উচিত: MY_VAR1 = "লাইন 1 ine n লাইন 2" সুতরাং এমওয়াই_ভিআর 1 যখন প্রকাশ হবে তখন এতে নতুন লাইনও থাকবে। অবশ্যই আপনার সমস্যা হতে পারে যদি আপনার সঞ্চিত মানটিতে চরটি থাকে "। তবে সেটিও যত্ন নেওয়া যেতে পারে।
ভাদিমবোগ

1
বিটিডব্লিউ, কেন এমন কিছু ভোট দেওয়া উচিত যা এখানে জিজ্ঞাসিত প্রশ্নের সঠিক উত্তর দিচ্ছে? উপরেরটি আমার জন্য খুব ভাল কাজ করে এবং আমার স্ক্রিপ্টগুলির সর্বত্র ব্যবহার করে?
ভাদিমবোগ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.