入力ファイルを編集するためのシェルスクリプトを作成しようとしています。入力ファイルのデータ構造は次のとおりです。
1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
最初の行で強調したように、ソートにはスペースを使用します。現在、sed
代替パラメータ(各行の最初の「単語」)を使用しています。
ラベルの並べ替えを混乱させない限り、これを行う方法を見つけることができません。私はどんな提案でも受け入れます。特に伝えようとしているわけではありませんsed
。たとえば、タブを使用して入力ファイルの構造を変更できます。
以下は、スクリプトで実行したい操作の例です。
input file
----------
1000␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
running the script
------------------
$ script --final-time=100
input file after running the script
-----------------------------------
100␣␣␣␣␣␣␣␣␣␣␣␣␣: final time
1000 : print time
0.1 : time step
代替文字列の長さはあらかじめわかりません。固定されておらず、最大6文字を含めることができます。
答え1
代わりに、awk
フィールドの形式を正しい幅で指定してくださいsprintf()
。これを使用するよりも簡単な可能性がありますsed
。
$ cat file
1000 : final time
1000 : print time
0.1 : time step
$ awk -F ':' -v sect=' final time' -v val='100' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
100 : final time
1000 : print time
0.1 : time step
これは別々のフィールドで構成される入力ラインを処理します:
。 2番目のフィールドがコマンドラインsect
で変数に割り当てられた文字列に対応する場合、最初のフィールドはコマンドラインawk
で割り当てられた値に置き換えられます。val
ここで使用されるsprintf()
フォーマット文字列はです%-16s
。にあることを確認してください:
。
同じコマンドを使用して「時間ステップ」を設定するには、sect
合計の異なる値を挿入するだけですval
。
$ awk -F ':' -v sect=' time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == sect { $1 = sprintf("%-16s", val) }; 1' file
1000 : final time
1000 : print time
0.12121212 : time step
値の先頭のスペースは、sect
データのスペースの後に考慮する必要があります:
。また、これを行うことができます
$ awk -F ':' -v sect='time step' -v val='0.12121212' 'BEGIN { OFS=FS } $2 == " " sect { $1 = sprintf("%-16s", val) }; 1' file
1000 : final time
1000 : print time
0.12121212 : time step
sect
(2番目の列の値をテストするために値のスペースを移動しました。)
スクリプトの提案(入力ファイルの静的ファイルパスを使用します。出力修正データ):
#!/bin/sh
filepath=some/file/path
if [ "$#" -ne 2 ]; then
echo expecting two arguments >&2
exit 1
fi
case $1 in
--final-time) sect='final time' ;;
--print-time) sect='print time' ;;
--time-step) sect='time step' ;;
*)
printf 'Unknown argument: %s\n' "$1" >&2
exit 1
esac
val=$2
awk -F ':' -v sect="$sect" -v val="$val" '
BEGIN { OFS=FS }
$2 == " " sect { $1 = sprintf("%-16s", val) }; 1' "$filepath"
答え2
少しsed
魔法
v=100; l=${#v}; sed -E "/final/s/[0-9.]/ /g; s/^[ ]{"$l"}/"$v"/" file
私たちはそれを探しているので、それを一致の前提条件にし、次を使用してすべてのfinal
数字と素数を削除します。[0-9.]
sed -E "/final/s/[0-9.]/ /g;
sed
前のスペースを置き換えるために後半部分を作成します{$l}
。$v
これは$l
ただの長さにすぎません。$v
s/^[ ]{"$l"}/"$v"/"
ミッション完了。