バイナリ値を含む2つのbash変数があるとします。
a=0011 # decimal 3
b=1000 # decimal 8
$a
可能なすべての値を繰り返し$b
バイナリに保つ方法はありますか?それは次のとおりです。
for blah in $(seq $a $b) ; do
print "Blah is: $blah"
done
したがって、次のように出力されます。
Blah is: 0011
Blah is: 0100
Blah is: 0101
Blah is: 0110
Blah is: 0111
Blah is: 1000
私は試した:
for blah in $(seq "$((2#$a))" "$((2#$b))") ; do
しかし、$blah
10進数になり、2進数で維持したいと思います。 (いつでも10進数を2進数に変換できますが、すでに厳しいバイナリ)
コードは限られたLinux(オープンWRT)使用できませんobase
。答えがこの場合バイナリ値を保存することは不可能です、これはまた便利な答えです(を使用せずに10進数を2進数に変換する関数を作成することができますobase
)も一般的ですbash
。
答え1
あなたはこれにかなり近いです:
for blah in $(seq "$((2#$a))" "$((2#$b))") ; do
for
同様の方法を使用して、ループ内の10進値を再び2進数に変換しますdc
。
はい
$ for blah in $(seq "$((2#0011))" "$((2#1000))"); do \
printf "%04d\n" $(echo "obase=2;$blah" | bc);done
0011
0100
0101
0110
0111
1000
printf
前にゼロが埋め込まれ、特定の幅にフォーマットされているように出力を制御するために使用されます。パラメーターは%04d
出力内容を指定します。
このコマンドのもう1つの重要な点は、bc
コマンドライン電卓を使用することです。このコマンドの例は次のとおりです。
echo "obase=2;$blah" | bc
を使用して値を取得し、$blah
2進数(2進数とも呼ばれる)に変換しますbc
。
BCまたはDCなし
これらのツールがまったく存在しないように制限されたシステムを使用している場合は、awk
マニュアルのこの機能を直接使用して変換できます。awk
はい
次の内容でファイルを作成し、名前をdec2bin.awk
。
# bits2str --- turn a byte into readable 1's and 0's
function bits2str(bits, data, mask)
{
if (bits == 0)
return "0"
mask = 1
for (; bits != 0; bits = rshift(bits, 1))
data = (and(bits, mask) ? "1" : "0") data
while ((length(data) % 8) != 0)
data = "0" data
return data
}
{
printf("%s\n", bits2str($1))
}
さて、上記の機能を使用してください。
$ for blah in $(seq "$((2#0011))" "$((2#1000))"); do echo $blah \
| awk -f dec2bin.awk; done
00000011
00000100
00000101
00000110
00000111
00001000
答え2
seq
内蔵されていません。また、Posix 標準の一部ではありません。ただし、一般的な実装では、seq
10 以外の基準でソートする機能はありません。
Bashでは範囲を{start..finish}
。{a..f}
a b c d e f
私が知る限り、これはいくつかの可能性を提供する単純なシーケンスジェネレータです。
愚かな方法は、バイナリではなく値をフィルタリングすることです。a
合計がb
非常に小さくはありませんが、非常に非効率的であれば、これは簡単です。
for x in $(seq -w $a $b); do
if [[ ! ($x =~ [2-9]) ]]; then
echo $x
fi
done
これがより良い解決策です。a
との長さが同じであると仮定するとb
(そうでない場合はprintfを使用してこの問題を解決できます)、以下はaからb(含む)までのすべての2進数を繰り返します。
# We need a string of 0s at least as long as a:
z=${a//1/0}
while [[ ! ($a > $b) ]]; do
# do something with $a
# The following "increments" a by removing the last 0 (and trailing 1s)
# and replacing that with a 1 and the same number of 0s.
a=$(printf "%.*s" ${#a} ${a%0*}1$z)
done
答え3
以下を使用する方が簡単ですzsh
。
for ((i=2#$a; i<=2#$b; i++)) echo $(([##2]i))
または 0 パディングを使用します。
for ((i=2#$a; i<=2#$b; i++)) printf '%04d\n' $(([##2]i))
それ以外の場合は、次のものを使用できますbc
。
echo "ibase=obase=2; for (i=$a; i<=$b; i++) i" | bc
またはdc
:
echo "2doi $a [p1+d$b!<a]dsax" | dc
0-padの場合、常に出力を次にパイプできます。
sed 's/^/000/;s/^0*\(.\{4\}\)/\1/'
答え4
この方法は多くの処理を実行するため、大規模には適していません。
seq -f '%04g' 0011 1000 | grep -v '[2-9]'