ファイルをソートしたままにして最初の単語を置き換える

ファイルをソートしたままにして最初の単語を置き換える

入力ファイルを編集するためのシェルスクリプトを作成しようとしています。入力ファイルのデータ構造は次のとおりです。

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"/"

ミッション完了。

関連情報