考慮以下動態變數,每次都可能發生變化。有時甚至可能有 5 個變數,但所有變數的長度每次都相同。
var1='a b c d e... upto z'
var2='1 2 3 4 5... upto 26'
var3='I II III IV V... upto XXVI'
我正在尋找一種通用的方法來迭代 for 回圈中的變數 & 我想要的輸出應該如下所示。
a,1,I
b,2,II
c,3,III
d,4,IV
e,5,V
.
.
goes on upto
z,26,XXVI
如果我使用嵌套回圈,那么我會得到所有可能的組合,這不是預期的結果。
另外,我知道如何使用 for 回圈使 2 個變數作業,并使用以下鏈接進行轉換 https://unix.stackexchange.com/questions/390283/how-to-iterate-two-variables-in-a-sh-腳本
uj5u.com熱心網友回復:
和 paste
paste -d , <(tr ' ' '\n' <<<"$var1") <(tr ' ' '\n' <<<"$var2") <(tr ' ' '\n' <<<"$var3")
a,1,I
b,2,II
c,3,III
d,4,IV
e...z,5...26,V...XXVI
但顯然必須為 morevarN的其他引數替換添加是不可擴展的。
uj5u.com熱心網友回復:
您需要一次“壓縮”兩個變數。
var1='a b c d e...z'
var2='1 2 3 4 5...26'
var3='I II III IV V...XXVI'
zip_var1_var2 () {
set $var1
for v2 in $var2; do
echo "$1,$v2"
shift
done
}
zip_var12_var3 () {
set $(zip_var1_var2)
for v3 in $var3; do
echo "$1,$v3"
shift
done
}
for x in $(zip_var12_var3); do
echo "$x"
done
如果您愿意使用eval并確定這樣做是安全的,您可以撰寫一個函式,如
zip () {
if [ $# -eq 1 ]; then
eval echo \$$1
return
fi
a1=$1
shift
x=$*
set $(eval echo \$$a1)
for v in $(zip $x); do
printf '=== %s\n' "$1,$v" >&2
echo "$1,$v"
shift
done
}
zip var1 var2 var3 # Note the arguments are the *names* of the variables to zip
如果您可以使用陣列,則(例如,在bash)
var1=(a b c d e)
var2=(1 2 3 4 5)
var3=(I II III IV V)
for i in "${!var1[@]}"; do
printf '%s,%s,%s\n' "${var1[i]}" "${var2[i]}" "${var3[i]}"
done
uj5u.com熱心網友回復:
使用這個 Perl 單行:
perl -le '@in = map { [split] } @ARGV; for $i ( 0..$#{ $in[0] } ) { print join ",", map { $in[$_][$i] } 0..$#in; }' "$var1" "$var2" "$var3"
印刷:
a,1,I
b,2,II
c,3,III
d,4,IV
e,5,V
z,26,XXVI
Perl 單行使用這些命令列標志:
-e: 告訴 Perl 查找內嵌代碼,而不是在檔案中。
-l:"\n"在執行行內代碼之前去除輸入行分隔符(默認情況下在 *NIX 上),并在列印時附加它。
輸入變數必須用雙引號“像這樣”參考,以防止空格分隔的單詞被視為單獨的引數。
@ARGV是命令列引數的陣列,這里是$var1, $var2, $var3。
@in是一個由 3 個元素組成的陣列,每個元素都是對一個陣列的參考,該陣列是拆分@ARGVon 空白的相應元素而獲得的。請注意,split默認情況下將字串拆分為空格,但您可以指定不同的分隔符,它接受正則運算式。
后續for回圈列印@in以逗號分隔的元素。
還請參見
perldoc perlrun::如何執行 Perl 解釋器:命令列開關
perldoc perlvar:Perl 預定義變數
uj5u.com熱心網友回復:
以下是(幾乎)此答案的副本,并進行了一些調整以使其適合此問題。
原始問題
首先讓我們分配一些變數來使用,每個變數中有 26 個標記:
var1="$(echo {a..z})"
var2="$(echo {1..26})"
var3="$(echo I II III IV \
V{,I,II,III} IX \
X{,I,II,III} XIV \
XV{,I,II,III} XIX \
XX{,I,II,III} XXIV \
XXV XXVI)"
var4="$(echo {A..Z})"
var5="$(echo {010101..262626..10101})"
現在我們想要一個“神奇”的函式來壓縮任意數量的變數,最好是在純 Bash 中:
zip_vars var1 # a trivial test
zip_vars var{1..2} # a slightly less trivial test
zip_vars var{1..3} # the original question
zip_vars var{1..4} # more vars, becasuse we can
zip_vars var{1..5} # more vars, because why not
可能是什么zip_vars樣子?這是純 Bash 中的一個,沒有任何外部命令:
zip_vars() {
local var
for var in "$@"; do
local -a "array_${var}"
local -n array_ref="array_${var}"
array_ref=(${!var})
local -ar "array_${var}"
done
local -n array_ref="array_${1}"
local -ir size="${#array_ref[@]}"
local -i i
local output
for ((i = 0; i < size; i)); do
output=
for var in "$@"; do
local -n array_ref="array_${var}"
output =",${array_ref[i]}"
done
printf '%s\n' "${output:1}"
done
}
這個怎么運作:
- 它將所有變數(通過參考(通過變數名稱)傳遞)拆分為陣列。
varX它為每個變數創建一個本地陣列array_varX。- 如果輸入變數已經是 Bash 陣列,那實際上會更容易(見下文),但是……我們最初堅持原始問題。
- 它確定
size第一個陣列的 ,然后盲目地期望所有陣列都是那個size。 - 對于
i從0到的每個索引,size - 1它連接i所有陣列的第 th 個元素,以,.
陣列讓事情變得更容易
如果您從一開始就使用 Bash 陣列,則腳本會更短且看起來更簡單,并且不會有任何字串到陣列的轉換。
zip_arrays() {
local -n array_ref="$1"
local -ir size="${#array_ref[@]}"
local -i i
local output
for ((i = 0; i < size; i)); do
output=
for arr in "$@"; do
local -n array_ref="$arr"
output =",${array_ref[i]}"
done
printf '%s\n' "${output:1}"
done
}
arr1=({a..z})
arr2=({1..26})
arr3=( I II III IV
V{,I,II,III} IX
X{,I,II,III} XIV
XV{,I,II,III} XIX
XX{,I,II,III} XXIV
XXV
XXVI)
arr4=({A..Z})
arr5=({010101..262626..10101})
zip_arrays arr1 # a trivial test
zip_arrays arr{1..2} # a slightly less trivial test
zip_arrays arr{1..3} # (almost) the original question
zip_arrays arr{1..4} # more arrays, becasuse we can
zip_arrays arr{1..5} # more arrays, because why not
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/317375.html
