解決策を見つけようとしています。これ質問。これまでこの問題を解決した方法は次のとおりです。
- すべての文字を一緒に追加して、1つの長い文字列を作成します。
- 上記の手順を完了した後、スペースまたはタブのスペースをすべて削除して、1つの大きな文字列だけを残します。
次のコマンドを使用して上記の手順を構築できました。
column -s '\t' inputfile | tr -d '[:space:]'
したがって、このような入力ファイルの場合
1 0 0 0 0 0
0 1 1 1 0 0
上記のコマンドを適用した後、私の値は次のようになります。
100000011100
それでは、この大きな文字列に次の方法を適用してみましょう。
元のOPで要求されているように、すべての6文字を抽出して文字列の最後まで配列要素に追加します。
したがって、基本的には上記の手順で次のように配列要素を作成しようとします。
10
(1番目と7番目の文字)、(2番目01
と8番目の文字)、(3番目と9番目の文字)、(4番目と10番目の文字)、(5番目と11番目の文字)、(6番目と12文字)最初の文字)最初の文字)。01
01
00
00
だから私の質問は、追加処理のために配列に追加できるようにすべてのn文字をどのように抽出できますか? (この場合 n=6)。
答え1
2行
bash
配列を生成するbash
純粋なソリューションは次のとおりです。
s="100000011100"
array=($(
for ((i=0; i<${#s}-6; i++))
do
echo "${s:$i:1}${s:$((i+6)):1}"
done
))
echo "${array[@]}"
これにより、質問に示されているのと同じ出力が生成されます。
10 01 01 01 00 00
ここで重要な要素はbashを使用することです。部分文字列拡張。 Bashを使用すると、parameter
viaなどの変数から部分文字列を抽出できます${parameter:offset:length}
。私たちの場合、オフセットはループ変数によって決まり、i
長さは常にです1
。
すべてのライン数に対する汎用ソリューション
たとえば、元の文字列が18文字であると仮定すると、iのi番目、i + 6番目、i + 12番目の文字を0から5まで抽出しようとします。だから:
s="100000011100234567"
array=($(
for ((i=0; i<6; i++))
do
new=${s:$i:1}
for ((j=i+6; j<${#s}; j=j+6))
do
new="$new${s:$j:1}"
done
echo "$new"
done
))
echo "${array[@]}"
これにより、次のような出力が生成されます。
102 013 014 015 006 007
同じコードを6文字の行に拡張できます。たとえば、s
3行(18文字)がある場合:
s="100000011100234567abcdef"
その後、出力は次のようになります。
102a 013b 014c 015d 006e 007f
答え2
使用perl
:
$ echo 100000011100 | perl -nle '
for ($i = 0; $i < length()/2; $i++) {
print substr($_,$i,1), substr($_,$i+6,1);
}
'
10
01
01
01
00
00
両方のラインで動作します。任意の行を処理するには、大きな文字列を作成するのではなく、行を直接処理する必要があります。次の入力を渡してください。
1 0 0 0 0 0
0 1 1 1 0 0
0 0 0 0 0 0
努力する:
$ perl -anle '
for ($i = 0; $i <= $#F; $i++) {
push @{$h{$i}}, $F[$i];
}
END {
print @{$h{$_}} for keys %h;
}
' file
000
010
000
100
010
010
答え3
シェルソリューションとして、getopts
おそらく最も簡単です。問題は、getopts
POSIXが指定されており、正確に目的の操作を実行することです。つまり、シェルループ内のバイトストリームを処理します。奇妙に聞こえるということを知っています。私がこの言葉を学ぶ前に皆さんも私と同じなら、次のように考えることもできますから。まあ、私はそれがコマンドラインスイッチを処理しなければならないと思いました。これは本当ですが、最初のものも同じです。考慮する:
-thisisonelongstringconsistingofseparatecommandlineswitches
はい、getopts
この問題を解決する必要があります。ループ内で文字ごとに分割し、シェル$OPTARG
変数または名前で指定された他の変数の各文字を返す必要があります。さらに重要なのは、シェル変数にエラーを返す必要があることです。進行状況を保存するシェル変数で実行されると$OPTIND
、中断したところから続くどういうわけか解決が可能なら。サブシェルを呼び出さずに操作全体を完了する必要があります。
次のような結果があるとします。
arg=$(seq -s '' 1000); set --
while getopts :0123456789 v -"${arg}"
do [ "$((i=$i+1<6?$i+1:0))" -gt 0 ] ||
set "$@" "$v"
done
うーん…動作しているのだろうか?
echo "$((${#arg}/6))" "$#"
482 482
大丈夫...
eval '
printf %.1s\\n "${arg#'"$(printf %0$((124*6-1))d | tr 0 \?)"'}" "${124}"'
4
4
したがって、このgetopts
コマンドは文字列の6バイトごとに配列を完全に設定します。このような数字である必要はなく、シェル安全文字でもあります。上記のようにターゲット文字を指定する必要もありません01234565789
。私はこれを多くのシェルで繰り返しテストしましたが、すべてうまくいきます。いくつかの珍しい点があります。bash
最初の文字が空白文字の場合は破棄されます。コロンは、POSIXが明示的に禁止する唯一の引数であるにもかかわらず、指定された引数としてdash
受け入れられます。:
しかし、問題ではありません。エラーを返しても、getopts
現在のopt char値は保存され続けるからです。$OPTARG
(指定されたopt変数に割り当てられた?で表されます)$OPTARG
それ以外の場合は、オプションに引数が必要であると宣言しない限り、明示的に設定が解除されます。スペースは良いです。スペースは1つだけ捨てます。リーダー不明な値を処理するときは、次のようにすることができます。
getopts : o -" $unknown_value"
...最初の文字が実際に受け入れるargs文字列にある危険なしにループを開始します。これにより、getopts
内容全体が$OPTARG
一度に引数として挿入されます。
別の例は次のとおりです。
OPTIND=1
while getopts : o -" $(dd if=/dev/urandom bs=16 count=1 2>/dev/null)"
do printf '\\%04o' "'$OPTARG"; done
\0040\0150\0071\0365\0320\0070\0161\0064\0274\0115\0012\0215\0222\0271\0146\0057\0166
$OPTIND=1
今使ったので最初の行に設定しましたが、getopts
リセットする前に次の呼び出しが中断された部分から続くことを期待します。"${arg2}"
つまり、欲しいものです。しかし、与えたくなく、今は別のことをしていて、$OPTIND
いつ始められるかをお知らせするためにリセットしました。
私が使用したこの文字では、zsh
先行スペースに反対しません。したがって、最初の文字は8進数40スペース文字です。しかし、私は通常getopts
このように使用しません。主に使用します。避けるwrite()
上記のように、各バイトに対して操作を実行し、その出力(変数の)を別のシェル変数に割り当てますset
。その後、準備ができたら文字列全体を取得できます。これにより通常は最初のバイトが削除されます。
答え4
sed
私の心に最初に浮かんだのは。
$ echo 1234567890abcdefghijklmnopqrstuvwxyz | sed 's/.\{5\}\(.\)/\1/g'
6bhntz
5つの文字を一致させ、6番目の文字をキャプチャし、すべてキャプチャされた文字に置き換えます。
しかし、文字列の長さが正確に6の倍数ではない場合、問題が発生します。
$ echo 1234567890abcdefghijklmnopqrstuvwxy | sed 's/.\{5\}\(.\)/\1/g'
6bhntuvwxy
ただし、sed
次のように少し変更すると、この問題を解決できます。
$ echo 1234567890abcdefghijklmnopqrstuvwxy | sed 's/.\{1,5\}\(.\{0,1\}\)/\1/g'
6bhnt
正規表現の欲張りな性質のため、可能であれば可変長一致が一致し、キャプチャする項目が残っていない場合はキャプチャされずに文字が削除されます。