この記事を読んでくれてありがとう。私はbashに初めて触れたので、次のアドバイスが必要です。
2つの列を含むファイルを読み取るbashスクリプトを作成したいと思います。
f 2
g 1
s 4
d 5
f 2
g 5
d 9
g 10
h 1
s 5
d 29
私のスクリプトは実際に最初の列(アルファベット)に基づいてファイルをソートし、という名前のファイルを生成し、数字で同じことを行い、alpha_sorted.txt
名前を付けたいと思いますnumbers_sorted.txt
。
私はこの分野に慣れていないので、可能であればあなたの助けを求めたいと思い、文書やリンクを提供したり、コードの助けを得たいと思います。
このスクリプトは初級レベルの使用のためであるため、アプローチを複雑にすることはお勧めできません。
修正する
john1024の答えを使用して、次の問題が発生しました。
Hasan@HasanChr /cygdrive/c/users/Hasan/Desktop/Bash
$ chmod +x script.sh
Hasan@HasanChr /cygdrive/c/users/Hasan/Desktop/Bash
$ ./script.sh
cat: alpha_sorted.txt: No such file or directory
スクリーンショットscript.sh
答え1
この記事がに投稿されて以来Unix.stackexchange.com、一般的なUNIXツールにアクセスできるとします。
最初の列はアルファベット順に並べられます。
$ sort file.txt >alpha_sorted.txt
$ cat alpha_sorted.txt
d 29
d 5
d 9
f 2
f 2
g 1
g 10
g 5
h 1
s 4
s 5
数値ソート:
$ sort -nk2,2 file.txt >numbers_sorted.txt
$ cat numbers_sorted.txt
g 1
h 1
f 2
f 2
s 4
d 5
g 5
s 5
d 9
g 10
d 29
-n
数値ソートを指定します。 -k2,2
ソートする2番目の列を指定します。
詳細についてはを参照してくださいman sort
。
メモ帳を使用してUnixスクリプトを編集するときに発生する問題
DOS行の終わりにスクリプトを作成しました。
$ cat dos.sh
sort file.txt >alpha_sorted.txt
cat alpha_sorted.txt
見えませんが、コマンドの最後にスペースを追加しましたcat
。このファイルを使用すると、表示されるエラーを再現できます。
$ chmod +x dos.sh
$ dos.sh
cat: alpha_sorted.txt: No such file or directory
: No such file or directory
dos2unix
またはなどのユーティリティを使用してこの問題を解決できますtr
。使用tr
:
$ tr -d '\r' <dos.sh >fixed.sh
$ chmod +x fixed.sh
これで、次のコマンドを正常に実行できます。
$ fixed.sh
d 29
d 5
d 9
f 2
f 2
g 1
g 10
g 5
h 1
s 4
s 5
答え2
より良いソート方法があります。bashでのみ行う代わりに。これはあなたの質問に対する良い答えではありません。単純ではなく(bashのいくつかの一般的な機能を使用しているため)、事前に構築されたタスクを実行するために使用されても、「Unix方式」ではタスクを実行しません。何かをし、それをうまくやってください(ソートなど)。
アカウントのデフォルトシェルがコマンドの実行とI / Oリダイレクト用に構築されていることを明確にするために、この回答を作成することにしました。殻があるという理由だけでBashなどのさまざまな機能特定の作業に最適なツールという意味ではありません。代わりに、awkまたはperl(またはjqまたはsort ...)を使用することを提案する答えをここでよく見ることができます。シェルスクリプトでハッキング。
そういえば、bashできるソート - 組み込みではありません。もう一度申し上げますが、これはまだ良い考えではありません。しかし、あなたはできます。以下は、bashに実装されている4つの機能です。タイプ2つのフィールドのそれぞれには2つの方法があります。
これらの機能は以下を使用します。
- ソート
- ローカル関数変数
- マップファイル
for ((
サイクル- 複雑パラメータの置換
- バッシュ
[[
テスト演算子実際のソートのために - 2つの値を解析するためのbashの
[[
テスト演算子 - バッシュ
read
組み込み
挿入ソートが効率的ではありません(O(n) 2)、しかし11行の例のような小さなデータセットは間違いなく合理的です。サンプルデータの場合、4つの関数が1秒未満で実行されたがランダムに生成された1,000行の入力ファイルの場合、「単一配列」のソートには約15秒かかり、「内部」バージョンは約60秒かかりました。再処理。これを比較する標準ソートユーティリティ1000分の1秒で、すべての列の1,000行のファイルを並べ替えます。
これら2つの「in-place」関数は、配列(そして値を繰り返し交換するためのいくつかの1回限りの変数)のみを生成していくつかのバイトを節約しようとし、きちんとしたbash関数を使用してファイルを変換します。配列として。 「キーイング」機能は風に注意を払います二つソートに必要なキーの配列と実際の値の配列を分離します。
function sort_inplace_f1 {
local array
mapfile -t array < "$1"
local i j tmp
for ((i=0; i <= ${#array[@]} - 2; i++))
do
for ((j=i + 1; j <= ${#array[@]} - 1; j++))
do
local ivalue jvalue
[[ ${array[i]} =~ ([^[:space:]]+)[[:space:]]+(.*) ]]
ivalue="${BASH_REMATCH[1]}"
[[ ${array[j]} =~ ([^[:space:]]+)[[:space:]]+(.*) ]]
jvalue=${BASH_REMATCH[1]}
if [[ $ivalue > $jvalue ]]
then
tmp=${array[i]}
array[i]=${array[j]}
array[j]=$tmp
fi
done
done
printf "%s\n" "${array[@]}"
}
function sort_inplace_f2 {
local array
mapfile -t array < "$1"
local i j tmp
for ((i=0; i <= ${#array[@]} - 2; i++))
do
for ((j=i + 1; j <= ${#array[@]} - 1; j++))
do
local ivalue jvalue
[[ ${array[i]} =~ ([^[:space:]]+)[[:space:]]+(.*) ]]
ivalue="${BASH_REMATCH[2]}"
[[ ${array[j]} =~ ([^[:space:]]+)[[:space:]]+(.*) ]]
jvalue=${BASH_REMATCH[2]}
if [[ $ivalue > $jvalue ]]
then
tmp=${array[i]}
array[i]=${array[j]}
array[j]=$tmp
fi
done
done
printf "%s\n" "${array[@]}"
}
function sort_keyed_f1 {
local c1 c2 keys values
while IFS=' ' read -r c1 c2
do
keys+=("$c1")
values+=("$c1 $c2")
done < "$1"
local i j tmpk tmpv
for ((i=0; i <= ${#keys[@]} - 2; i++))
do
for ((j=i + 1; j <= ${#keys[@]} - 1; j++))
do
if [[ ${keys[i]} > ${keys[j]} ]]
then
# swap keys
tmpk=${keys[i]}
keys[i]=${keys[j]}
keys[j]=$tmpk
# swap values
tmpv=${values[i]}
values[i]=${values[j]}
values[j]=$tmpv
fi
done
done
printf "%s\n" "${values[@]}"
}
function sort_keyed_f2 {
local c1 c2 keys values
while IFS=' ' read -r c1 c2
do
keys+=("$c2")
values+=("$c1 $c2")
done < "$1"
local i j tmpk tmpv
for ((i=0; i <= ${#keys[@]} - 2; i++))
do
for ((j=i + 1; j <= ${#keys[@]} - 1; j++))
do
if [[ ${keys[i]} -gt ${keys[j]} ]]
then
# swap keys
tmpk=${keys[i]}
keys[i]=${keys[j]}
keys[j]=$tmpk
# swap values
tmpv=${values[i]}
values[i]=${values[j]}
values[j]=$tmpv
fi
done
done
printf "%s\n" "${values[@]}"
}
これらすべてがあった後でも、まだシェルの重要な「機能」の1つ、つまり出力をファイルにリダイレクトする必要があります。
sort_keyed_f1 input-file > alpha_sorted.txt
sort_keyed_f2 input-file > numbers_sorted.txt