हमें एक स्क्रिप्ट की आवश्यकता है जो शेल स्क्रिप्टिंग, किसी भी निकाय के लिए डेटा संरचना की तरह साहचर्य सरणियों या मानचित्र का अनुकरण करती है?
हमें एक स्क्रिप्ट की आवश्यकता है जो शेल स्क्रिप्टिंग, किसी भी निकाय के लिए डेटा संरचना की तरह साहचर्य सरणियों या मानचित्र का अनुकरण करती है?
जवाबों:
इरफान के जवाब में जोड़ने के लिए , यहाँ एक छोटा और तेज़ संस्करण है get()
क्योंकि इसके लिए मानचित्र सामग्री पर कोई पुनरावृत्ति की आवश्यकता नहीं है:
get() {
mapName=$1; key=$2
map=${!mapName}
value="$(echo $map |sed -e "s/.*--${key}=\([^ ]*\).*/\1/" -e 's/:SP:/ /g' )"
}
एक अन्य विकल्प, यदि पोर्टेबिलिटी आपकी मुख्य चिंता नहीं है, तो शेल के लिए बनाई गई साहचर्य सरणियों का उपयोग करना है। यह bash 4.0 में काम करना चाहिए (अब सबसे बड़े डिस्ट्रो पर उपलब्ध है, हालाँकि OS X पर नहीं जब तक कि आप इसे स्वयं इंस्टॉल न करें), ksh, और zsh:
declare -A newmap
newmap[name]="Irfan Zulfiqar"
newmap[designation]=SSE
newmap[company]="My Own Company"
echo ${newmap[company]}
echo ${newmap[name]}
शेल के आधार पर, आपको typeset -A newmap
इसके बजाय करने की आवश्यकता हो सकती है declare -A newmap
, या कुछ में यह बिल्कुल भी आवश्यक नहीं हो सकता है।
test -z ${variable+x}
( x
कोई फर्क नहीं पड़ता, कि कोई भी स्ट्रिंग हो सकती है)। बैश में एक साहचर्य सरणी के लिए, आप समान कर सकते हैं; उपयोग करें test -z ${map[key]+x}
।
एक और नॉन-बैश 4 तरीका।
#!/bin/bash
# A pretend Python dictionary with bash 3
ARRAY=( "cow:moo"
"dinosaur:roar"
"bird:chirp"
"bash:rock" )
for animal in "${ARRAY[@]}" ; do
KEY=${animal%%:*}
VALUE=${animal#*:}
printf "%s likes to %s.\n" "$KEY" "$VALUE"
done
echo -e "${ARRAY[1]%%:*} is an extinct animal which likes to ${ARRAY[1]#*:}\n"
तुम वहाँ के रूप में अच्छी तरह से खोज के लिए एक अगर बयान फेंक सकता है। अगर [[$ var = ~ / blah /]]। जो कुछ भी।
मुझे लगता है कि आपको एक कदम और सोचने की ज़रूरत है कि वास्तव में नक्शा, या साहचर्य सरणी क्या है। यह सब किसी दिए गए कुंजी के लिए एक मूल्य को संग्रहीत करने का एक तरीका है, और उस मूल्य को जल्दी और कुशलता से वापस प्राप्त करता है। आप हर कुंजी मान जोड़ी को पुनः प्राप्त करने, या कुंजियों और उनके संबंधित मूल्यों को हटाने के लिए कुंजियों पर पुनरावृति करने में सक्षम होना चाह सकते हैं।
अब, एक डेटा संरचना के बारे में सोचें जो आप शेल स्क्रिप्टिंग में हर समय उपयोग करते हैं, और यहां तक कि शेल में सिर्फ एक स्क्रिप्ट लिखे बिना, जिसमें ये गुण हैं। स्टम्प्ड? यह फाइलसिस्टम है।
वास्तव में, आपको शेल प्रोग्रामिंग में एक सहयोगी सरणी होना चाहिए, यह एक अस्थायी निर्देशिका है। mktemp -d
आपका सहयोगी सरणी निर्माता है:
prefix=$(basename -- "$0")
map=$(mktemp -dt ${prefix})
echo >${map}/key somevalue
value=$(cat ${map}/key)
यदि आप का उपयोग करने का मन नहीं है echo
और cat
, आप हमेशा कुछ छोटे रैपर लिख सकते हैं; इन लोगों को इरफ़ान के मॉडल से अलग किया जाता है, हालांकि वे मनमाने ढंग से चर सेट करने के बजाय केवल मूल्य का उत्पादन करते हैं $value
:
#!/bin/sh
prefix=$(basename -- "$0")
mapdir=$(mktemp -dt ${prefix})
trap 'rm -r ${mapdir}' EXIT
put() {
[ "$#" != 3 ] && exit 1
mapname=$1; key=$2; value=$3
[ -d "${mapdir}/${mapname}" ] || mkdir "${mapdir}/${mapname}"
echo $value >"${mapdir}/${mapname}/${key}"
}
get() {
[ "$#" != 2 ] && exit 1
mapname=$1; key=$2
cat "${mapdir}/${mapname}/${key}"
}
put "newMap" "name" "Irfan Zulfiqar"
put "newMap" "designation" "SSE"
put "newMap" "company" "My Own Company"
value=$(get "newMap" "company")
echo $value
value=$(get "newMap" "name")
echo $value
संपादित करें : यह दृष्टिकोण वास्तव में प्रश्नकर्ता द्वारा सुझाए गए सेड के उपयोग से रैखिक खोज की तुलना में काफी तेज है, साथ ही साथ और अधिक मजबूत है (यह कुंजी और मूल्यों को शामिल करने की अनुमति देता है -, =, अंतरिक्ष, qnd ": SP:")। तथ्य यह है कि यह फाइल सिस्टम का उपयोग करता है, इसे धीमा नहीं करता है; जब तक आप कॉल नहीं करते ये डिस्क वास्तव में डिस्क पर लिखे जाने की गारंटी नहीं है sync
; एक छोटे जीवनकाल के साथ इस तरह की अस्थायी फ़ाइलों के लिए, यह संभावना नहीं है कि उनमें से कई डिस्क पर कभी नहीं लिखे जाएंगे।
मैंने इरफ़ान के कोड के कुछ बेंचमार्क किए, जेरी ने इरफ़ान के कोड का संशोधन किया, और मेरे कोड ने निम्नलिखित ड्राइवर प्रोग्राम का उपयोग किया:
#!/bin/sh
mapimpl=$1
numkeys=$2
numvals=$3
. ./${mapimpl}.sh #/ <- fix broken stack overflow syntax highlighting
for (( i = 0 ; $i < $numkeys ; i += 1 ))
do
for (( j = 0 ; $j < $numvals ; j += 1 ))
do
put "newMap" "key$i" "value$j"
get "newMap" "key$i"
done
done
परिणाम:
$ समय ।/driver.sh इरफान 10 5 वास्तविक 0m0.975s उपयोगकर्ता 0m0.280s sys 0m0.691s $ समय ।/driver.sh ब्रायन 10 5 असली 0m0.226s उपयोगकर्ता 0m0.057s sys 0m0.123s $ समय ।/driver.sh जेरी 10 5 असली 0m0.706s उपयोगकर्ता 0m0.228s sys 0m0.530s $ समय ।/driver.sh इरफान 100 5 असली 0m10.633s उपयोगकर्ता 0m4.366s sys 0m7.127s $ समय ।/driver.sh ब्रायन 100 5 असली 0m1.682s उपयोगकर्ता 0m0.546s sys 0m1.082s $ समय ।/driver.sh जेरी 100 5 असली 0m9.315s उपयोगकर्ता 0m4.565s sys 0m5.446s $ समय ।/driver.sh इरफान 10 500 असली 1m46.197s उपयोगकर्ता 0m44.869s sys 1m12.282s $ समय ।/driver.sh ब्रायन 10 500 वास्तविक 0m16.003s उपयोगकर्ता 0m5.135s sys 0m10.396s $ समय ।/driver.sh जेरी 10 500 वास्तविक 1m24.414s उपयोगकर्ता 0m39.696s sys 0m54.834s $ समय ।/driver.sh इरफान 1000 5 असली 4m25.145s उपयोगकर्ता 3m17.286s sys 1m21.490s $ समय ।/driver.sh ब्रायन 1000 5 असली 0m19.442s उपयोगकर्ता 0m5.287s sys 0m10.751s $ समय ।/driver.sh जेरी 1000 5 असली 5m29.136s उपयोगकर्ता 4m48.926s sys 0m59.336s
Bash4 इसे मूल रूप से समर्थन करता है। उपयोग न करें grep
या eval
, वे हैक के सबसे बदसूरत हैं।
एक क्रिया के लिए, उदाहरण कोड के साथ विस्तृत जवाब देखें: /programming/3467959
####################################################################
# Bash v3 does not support associative arrays
# and we cannot use ksh since all generic scripts are on bash
# Usage: map_put map_name key value
#
function map_put
{
alias "${1}$2"="$3"
}
# map_get map_name key
# @return value
#
function map_get
{
alias "${1}$2" | awk -F"'" '{ print $2; }'
}
# map_keys map_name
# @return map keys
#
function map_keys
{
alias -p | grep $1 | cut -d'=' -f1 | awk -F"$1" '{print $2; }'
}
उदाहरण:
mapName=$(basename $0)_map_
map_put $mapName "name" "Irfan Zulfiqar"
map_put $mapName "designation" "SSE"
for key in $(map_keys $mapName)
do
echo "$key = $(map_get $mapName $key)
done
अब इस सवाल का जवाब दे रहे हैं।
निम्नलिखित स्क्रिप्ट शेल स्क्रिप्ट में साहचर्य सरणियों का अनुकरण करती है। इसका सरल और समझने में बहुत आसान है।
मानचित्र कुछ भी नहीं है, लेकिन कभी खत्म होने वाली स्ट्रिंग नहीं है, जिसमें keyValuePair को सहेजा गया है --name = Irfan --designation = SSE --company = My: SP: खुद: SP: कंपनी
मानों के लिए रिक्त स्थान ': SP:' से बदल दिए गए हैं
put() {
if [ "$#" != 3 ]; then exit 1; fi
mapName=$1; key=$2; value=`echo $3 | sed -e "s/ /:SP:/g"`
eval map="\"\$$mapName\""
map="`echo "$map" | sed -e "s/--$key=[^ ]*//g"` --$key=$value"
eval $mapName="\"$map\""
}
get() {
mapName=$1; key=$2; valueFound="false"
eval map=\$$mapName
for keyValuePair in ${map};
do
case "$keyValuePair" in
--$key=*) value=`echo "$keyValuePair" | sed -e 's/^[^=]*=//'`
valueFound="true"
esac
if [ "$valueFound" == "true" ]; then break; fi
done
value=`echo $value | sed -e "s/:SP:/ /g"`
}
put "newMap" "name" "Irfan Zulfiqar"
put "newMap" "designation" "SSE"
put "newMap" "company" "My Own Company"
get "newMap" "company"
echo $value
get "newMap" "name"
echo $value
संपादित करें: सभी कुंजियों को लाने के लिए बस एक और तरीका जोड़ा गया।
getKeySet() {
if [ "$#" != 1 ];
then
exit 1;
fi
mapName=$1;
eval map="\"\$$mapName\""
keySet=`
echo $map |
sed -e "s/=[^ ]*//g" -e "s/\([ ]*\)--/\1/g"
`
}
eval
डेटा को आईएनजी के रूप में यद्यपि यह बैश कोड है, और क्या अधिक है: आप इसे ठीक से उद्धृत करने में विफल। दोनों ही बगों की भीड़ और मनमाने कोड इंजेक्शन का कारण बनते हैं।
बैश 3 के लिए, एक विशेष मामला है जिसका एक अच्छा और सरल समाधान है:
यदि आप बहुत सारे चर नहीं संभालना चाहते हैं, या कुंजियाँ केवल अमान्य चर पहचानकर्ता हैं, और आपके सरणी में 256 से कम आइटम होने की गारंटी है , तो आप फ़ंक्शन रिटर्न मान का दुरुपयोग कर सकते हैं। इस समाधान के लिए किसी उपधारा की आवश्यकता नहीं है क्योंकि मूल्य आसानी से एक चर के रूप में उपलब्ध है, और न ही कोई पुनरावृत्ति ताकि प्रदर्शन चिल्लाए। इसके अलावा यह बहुत पठनीय है, लगभग बैश 4 संस्करण की तरह।
यहाँ सबसे मूल संस्करण है:
hash_index() {
case $1 in
'foo') return 0;;
'bar') return 1;;
'baz') return 2;;
esac
}
hash_vals=("foo_val"
"bar_val"
"baz_val");
hash_index "foo"
echo ${hash_vals[$?]}
याद रखें, एकल उद्धरणों का उपयोग करें case
, अन्यथा यह ग्लोबिंग के अधीन है। शुरू से ही स्थिर / जमे हुए हैश के लिए वास्तव में उपयोगी है, लेकिन एक hash_keys=()
सरणी से एक सूचकांक जनरेटर लिख सकता है ।
बाहर देखें, यह पहले वाले को डिफॉल्ट करता है, इसलिए आप शून्य तत्व को अलग करना चाहते हैं:
hash_index() {
case $1 in
'foo') return 1;;
'bar') return 2;;
'baz') return 3;;
esac
}
hash_vals=("", # sort of like returning null/nil for a non existent key
"foo_val"
"bar_val"
"baz_val");
hash_index "foo" || echo ${hash_vals[$?]} # It can't get more readable than this
कैविएट: लंबाई अब गलत है।
वैकल्पिक रूप से, यदि आप शून्य-आधारित इंडेक्सिंग रखना चाहते हैं, तो आप किसी अन्य इंडेक्स वैल्यू और गैर-मौजूद कुंजी के खिलाफ गार्ड रख सकते हैं, लेकिन यह कम पठनीय है:
hash_index() {
case $1 in
'foo') return 0;;
'bar') return 1;;
'baz') return 2;;
*) return 255;;
esac
}
hash_vals=("foo_val"
"bar_val"
"baz_val");
hash_index "foo"
[[ $? -ne 255 ]] && echo ${hash_vals[$?]}
या, लंबाई को सही रखने के लिए, अनुक्रमणिका को एक से हटाएं:
hash_index() {
case $1 in
'foo') return 1;;
'bar') return 2;;
'baz') return 3;;
esac
}
hash_vals=("foo_val"
"bar_val"
"baz_val");
hash_index "foo" || echo ${hash_vals[$(($? - 1))]}
आप डायनामिक वैरिएबल नामों का उपयोग कर सकते हैं और चर नामों को हैशमैप की कुंजी की तरह काम कर सकते हैं।
उदाहरण के लिए, यदि आपके पास उदाहरण कॉलम के रूप में दो कॉलम, नाम, क्रेडिट के साथ एक इनपुट फ़ाइल है, और आप प्रत्येक उपयोगकर्ता की आय का योग करना चाहते हैं:
Mary 100
John 200
Mary 50
John 300
Paul 100
Paul 400
David 100
आदेश bellow, कुंजी के रूप में गतिशील चरों का उपयोग के रूप में, सब कुछ योग होगा नक्शा _ $ {व्यक्ति} :
while read -r person money; ((map_$person+=$money)); done < <(cat INCOME_REPORT.log)
परिणाम पढ़ने के लिए:
set | grep map
आउटपुट होगा:
map_David=100
map_John=500
map_Mary=150
map_Paul=500
इन तकनीकों पर विस्तार करते हुए, मैं GitHub पर एक फ़ंक्शन विकसित कर रहा हूं, जो एक HashMap ऑब्जेक्ट , shell_map की तरह काम करता है ।
" HashMap उदाहरण " बनाने के लिए शेल_मैप फ़ंक्शन विभिन्न नामों के तहत स्वयं की प्रतियां बनाने में सक्षम है। प्रत्येक नई फ़ंक्शन कॉपी में एक अलग $ FUNCNAME चर होगा। $ FUNCNAME का उपयोग तब प्रत्येक मानचित्र उदाहरण के लिए नाम स्थान बनाने के लिए किया जाता है।
मैप कुंजियाँ वैश्विक चर हैं, $ FUNCNAME_DATA_ $ कुंजी के रूप में, जहाँ $ KEY मानचित्र में जोड़ी गई कुंजी है। ये चर गतिशील चर हैं ।
Bellow मैं इसका एक सरलीकृत संस्करण डालूँगा ताकि आप उदाहरण के रूप में उपयोग कर सकें।
#!/bin/bash
shell_map () {
local METHOD="$1"
case $METHOD in
new)
local NEW_MAP="$2"
# loads shell_map function declaration
test -n "$(declare -f shell_map)" || return
# declares in the Global Scope a copy of shell_map, under a new name.
eval "${_/shell_map/$2}"
;;
put)
local KEY="$2"
local VALUE="$3"
# declares a variable in the global scope
eval ${FUNCNAME}_DATA_${KEY}='$VALUE'
;;
get)
local KEY="$2"
local VALUE="${FUNCNAME}_DATA_${KEY}"
echo "${!VALUE}"
;;
keys)
declare | grep -Po "(?<=${FUNCNAME}_DATA_)\w+((?=\=))"
;;
name)
echo $FUNCNAME
;;
contains_key)
local KEY="$2"
compgen -v ${FUNCNAME}_DATA_${KEY} > /dev/null && return 0 || return 1
;;
clear_all)
while read var; do
unset $var
done < <(compgen -v ${FUNCNAME}_DATA_)
;;
remove)
local KEY="$2"
unset ${FUNCNAME}_DATA_${KEY}
;;
size)
compgen -v ${FUNCNAME}_DATA_${KEY} | wc -l
;;
*)
echo "unsupported operation '$1'."
return 1
;;
esac
}
उपयोग:
shell_map new credit
credit put Mary 100
credit put John 200
for customer in `credit keys`; do
value=`credit get $customer`
echo "customer $customer has $value"
done
credit contains_key "Mary" && echo "Mary has credit!"
अभी तक एक और गैर-बैश -4 (यानी, बैश 3, मैक-संगत) तरीका:
val_of_key() {
case $1 in
'A1') echo 'aaa';;
'B2') echo 'bbb';;
'C3') echo 'ccc';;
*) echo 'zzz';;
esac
}
for x in 'A1' 'B2' 'C3' 'D4'; do
y=$(val_of_key "$x")
echo "$x => $y"
done
प्रिंटों:
A1 => aaa
B2 => bbb
C3 => ccc
D4 => zzz
साथ समारोह case
एक साहचर्य सरणी की तरह कार्य करता है। दुर्भाग्य से इसका उपयोग नहीं किया जा सकता है return
, इसलिए echo
इसके आउटपुट के लिए है, लेकिन यह एक समस्या नहीं है, जब तक कि आप एक शुद्धतावादी नहीं हैं जो उप-नक्षत्रों को त्यागने के लिए दूर है।
इससे पहले कि मैं इस सवाल पर दया नहीं करता था - मैंने लाइब्रेरी शेल-फ्रेमवर्क लिखा है जिसमें दूसरों के नक्शे (एसोसिएटिव एरे) शामिल हैं। इसका अंतिम संस्करण यहां पाया जा सकता है ।
उदाहरण:
#!/bin/bash
#include map library
shF_PATH_TO_LIB="/usr/lib/shell-framework"
source "${shF_PATH_TO_LIB}/map"
#simple example get/put
putMapValue "mapName" "mapKey1" "map Value 2"
echo "mapName[mapKey1]: $(getMapValue "mapName" "mapKey1")"
#redefine old value to new
putMapValue "mapName" "mapKey1" "map Value 1"
echo "after change mapName[mapKey1]: $(getMapValue "mapName" "mapKey1")"
#add two new pairs key/values and print all keys
putMapValue "mapName" "mapKey2" "map Value 2"
putMapValue "mapName" "mapKey3" "map Value 3"
echo -e "mapName keys are \n$(getMapKeys "mapName")"
#create new map
putMapValue "subMapName" "subMapKey1" "sub map Value 1"
putMapValue "subMapName" "subMapKey2" "sub map Value 2"
#and put it in mapName under key "mapKey4"
putMapValue "mapName" "mapKey4" "subMapName"
#check if under two key were placed maps
echo "is map mapName[mapKey3]? - $(if isMap "$(getMapValue "mapName" "mapKey3")" ; then echo Yes; else echo No; fi)"
echo "is map mapName[mapKey4]? - $(if isMap "$(getMapValue "mapName" "mapKey4")" ; then echo Yes; else echo No; fi)"
#print map with sub maps
printf "%s\n" "$(mapToString "mapName")"
मैंने इसे सही पाया है, जैसा कि पहले ही उल्लेख किया गया है, कि सबसे अच्छा प्रदर्शन करने का तरीका किसी फ़ाइल में कुंजी / वैल लिखना है, और फिर उन्हें पुनः प्राप्त करने के लिए grep / awk का उपयोग करें। यह अनावश्यक IO के सभी प्रकार की तरह लगता है, लेकिन डिस्क कैश में किक करता है और इसे बहुत ही कुशल बनाता है - उपरोक्त तरीकों में से एक का उपयोग करके मेमोरी में उन्हें स्टोर करने की कोशिश करने की तुलना में बहुत तेज़ है (जैसा कि बेंचमार्क शो)।
यहां मुझे एक त्वरित, स्वच्छ विधि पसंद है:
hinit() {
rm -f /tmp/hashmap.$1
}
hput() {
echo "$2 $3" >> /tmp/hashmap.$1
}
hget() {
grep "^$2 " /tmp/hashmap.$1 | awk '{ print $2 };'
}
hinit capitols
hput capitols France Paris
hput capitols Netherlands Amsterdam
hput capitols Spain Madrid
echo `hget capitols France` and `hget capitols Netherlands` and `hget capitols Spain`
यदि आप प्रति कुंजी एकल-मूल्य लागू करना चाहते हैं, तो आप hput () में थोड़ा grep / sed कार्रवाई भी कर सकते हैं।
कई साल पहले मैंने बैश के लिए स्क्रिप्ट लाइब्रेरी लिखी थी जो अन्य विशेषताओं (लॉगिंग, कॉन्फ़िगरेशन फ़ाइलों, कमांड लाइन तर्क के लिए विस्तारित समर्थन, सहायता, यूनिट परीक्षण, आदि) के बीच सहयोगी सरणियों का समर्थन करती थी। लाइब्रेरी में साहचर्य सरणियों के लिए एक आवरण होता है और स्वचालित रूप से उपयुक्त मॉडल (bash4 के लिए आंतरिक और पिछले संस्करणों के लिए अनुकरण) पर स्विच होता है। इसे शेल-फ्रेमवर्क कहा जाता था और इसकी उत्पत्ति .o.zz.ch पर की गई थी, लेकिन आज संसाधन बंद है। अगर किसी को अभी भी इसकी आवश्यकता है तो मैं इसे आपके साथ साझा कर सकता हूं।
शेल में डेटा संरचना जैसी कोई अंतर्निहित मानचित्र नहीं है, मैं उस तरह की वस्तुओं का वर्णन करने के लिए कच्चे स्ट्रिंग का उपयोग करता हूं:
ARRAY=(
"item_A|attr1|attr2|attr3"
"item_B|attr1|attr2|attr3"
"..."
)
जब आइटम निकालें और इसकी विशेषताएं:
for item in "${ARRAY[@]}"
do
item_name=$(echo "${item}"|awk -F "|" '{print $1}')
item_attr1=$(echo "${item}"|awk -F "|" '{print $2}')
item_attr2=$(echo "${item}"|awk -F "|" '{print $3}')
echo "${item_name}"
echo "${item_attr1}"
echo "${item_attr2}"
done
ऐसा लगता है कि अन्य लोगों के उत्तर की तुलना में चालाक नहीं है, लेकिन नए लोगों के लिए समझना आसान है।
मैंने निम्नलिखित के साथ वादिम के समाधान को संशोधित किया:
####################################################################
# Bash v3 does not support associative arrays
# and we cannot use ksh since all generic scripts are on bash
# Usage: map_put map_name key value
#
function map_put
{
alias "${1}$2"="$3"
}
# map_get map_name key
# @return value
#
function map_get {
if type -p "${1}$2"
then
alias "${1}$2" | awk -F "'" '{ print $2; }';
fi
}
# map_keys map_name
# @return map keys
#
function map_keys
{
alias -p | grep $1 | cut -d'=' -f1 | awk -F"$1" '{print $2; }'
}
यदि आप एक ऐसी कुंजी का अनुरोध करते हैं जो मौजूद नहीं है, तो इसे वापस करने में त्रुटियों को रोकने के लिए यह परिवर्तन map_get के लिए है, हालांकि इसका साइड-इफ़ेक्ट यह है कि यह मौन रूप से गुम हुए नक्शों को नज़रअंदाज़ कर देगा, लेकिन यह मेरे उपयोग के मामले को बेहतर बनाता है क्योंकि मैं अभी एक लूप में आइटम को छोड़ने के लिए एक कुंजी की जांच करना चाहता था।
देर से जवाब, लेकिन इस तरह से समस्या को संबोधित करने पर विचार करें, इस प्रकार के रूप में पढ़े जाने वाले एक ufw फ़ायरवॉल स्क्रिप्ट से कोड स्निपेट के भीतर सचित्र के रूप में पढ़े गए बैश बिलिन का उपयोग करें। इस दृष्टिकोण को वांछित के रूप में कई सीमांकित फ़ील्ड सेट (केवल 2 नहीं) का उपयोग करने का लाभ है। हमने इस्तेमाल किया है | सीमांकक क्योंकि पोर्ट रेंज स्पेसर्स के लिए एक बृहदान्त्र की आवश्यकता हो सकती है, अर्थात 6001: 6010 ।
#!/usr/bin/env bash
readonly connections=(
'192.168.1.4/24|tcp|22'
'192.168.1.4/24|tcp|53'
'192.168.1.4/24|tcp|80'
'192.168.1.4/24|tcp|139'
'192.168.1.4/24|tcp|443'
'192.168.1.4/24|tcp|445'
'192.168.1.4/24|tcp|631'
'192.168.1.4/24|tcp|5901'
'192.168.1.4/24|tcp|6566'
)
function set_connections(){
local range proto port
for fields in ${connections[@]}
do
IFS=$'|' read -r range proto port <<< "$fields"
ufw allow from "$range" proto "$proto" to any port "$port"
done
}
set_connections