私はシェルスクリプトを必要とする研究プロジェクトを進めています。プログラミング経験はありますが、経験はほとんどありません。問題のファイルは次のとおりです。
export OMP_NUM_THREADS=12
read controls
#inlist directory
export MESA_INLIST="/home/nick/mesa-r11701/star/test_suite/rsp_Cepheid_grid/inlist"
sed -i -e 's/.*extra_star_job_inlist2_name.*/extra_star_job_inlist2_name = '"'"''$controls"""'"'/i' $MESA_INLIST
sed -i -e 's/.*extra_controls_inlist2_name.*/extra_controls_inlist2_name = '"'"''$controls"""'"'/i' $MESA_INLIST
2番目のファイルの入力を変更するためにこのファイルを借りました/home/nick/mesa-r11701/star/test_suite/rsp_Cepheid_grid/inlist
。特に、extra_controls_inlist2_name
変数extra_star_job_inlist2_name
(等号の右に続く変数)です。
! this is the master inlist that MESA reads when it starts.
! This file tells MESA to go look elsewhere for its configuration
! info. This makes changing between different inlists easier, by
! allowing you to easily change the name of the file that gets read.
&star_job
read_extra_star_job_inlist1 = .true.
extra_star_job_inlist1_name = 'inlist_0all'
read_extra_star_job_inlist2 = .true.
extra_star_job_inlist2_name = 'inlist_3ms'
/ ! end of star_job namelist
&controls
read_extra_controls_inlist1 = .true.
extra_controls_inlist1_name = 'inlist_0all'
read_extra_controls_inlist2 = .true.
extra_controls_inlist2_name = 'inlist_3ms'
/ ! end of controls namelist
&pgstar
/ ! end of pgstar namelist
私はすでにコマンドとその機能についてexport
よく知っています。read
私はsedがテキストを見つけて置き換えるストリームエディタであることを知っており、これが2番目のファイルの私の目標です。しかし、-i -e
これらのオプションの役割は正確に何ですか?周りに引用文がなぜこんなにたくさんありますか$controls$
? sedコマンドでtheとtheはどういう/.*
意味ですか?/i
オンラインで予備検索しようとしましたが、適切な回答が見つかりませんでした。
答え1
-e
「次のコマンドライン引数はsed
式です」を意味します。-i
「こうして編集してください」という意味です。所定の位置につまり、元のファイルを変更します。」このオプションは非標準であり、sed
異なるUnixシステムで異なる実装間で移動すると混乱を招く可能性があります。sed -i(所定の位置で編集)を使用して移植性を達成するには?/.*
置換するテキストに一致する正規表現の始まりです。実際には、(代替)コマンドの区切り文字で正規表現/
の始まりです。それ自体は「任意の文字数と一致」を意味します。s///
sed
.*extra_star_job_inlist2_name.*
.*
.*
式の終わりにも表示され.*extra_star_job_inlist2_name.*
、その効果は文字列を含むすべての行が完全に置き換えられることです(つまり、置換はその行の文字列extra_star_job_inlist2_name
にのみ影響しません)。extra_star_job_inlist2_name
/i
繰り返しますが、これは/
コマンドの区切り記号であり、その後にs///
sed
バナーコマンドのためにs///
。このフラグは非標準で、GNUスタイルでのみ使用されますsed
。このフラグは、大文字と小文字を区別しない式の一致を作成します。バラよりGNUsed
ドキュメントこれに。周りの奇妙な引用
$controls
:- 式は
sed
一重引用符で囲まれた文字列として提供されます。一重引用符で囲まれた文字列なので、変数は拡張されません。変数値を挿入する前に、一重引用符で囲まれた文字列を終了する必要があります。これが最初です'
。 - その後、コードライターは文字通り一重引用符を挿入しようとしました。この目的のために、彼らは次のように引用します
"'"
。ここでも利用可能です\'
。 - その後、何らかの理由で、その後に一重引用符の空の文字列が続きます。
''
- その後、(引用されていない)値が続きます
$controls
。 - 別の空の二重引用符文字列
""
。 - 他の引用のための一重引用符、
"'"
。 - その後、式は
sed
一重引用符で囲まれた文字列に続きます。
- 式は
次の引用にはいくつかの問題があります$controls
。
- 2つの空の文字列があります。
- 拡張は
$controls
引用されていません。
これらの問題を回避するより良い変形は次のとおりです。
sed -i -e "s/.*extra_star_job_inlist2_name.*/extra_star_job_inlist2_name = '$controls'/i" "$MESA_INLIST"
つまり、sed
式全体に二重引用符で囲まれた文字列を使用できます(また、正しく引用した場合はエクスポート$MESA_INLIST
btwを使用する必要はありませんexport
)。これはsed
、式自体にバックスラッシュや文字が含まれていない限り機能します(これらと$
エスケープする必要があります)。\\
\$
または少し短くするには、キャプチャグループを使用して代替テキストで繰り返す文字列をキャプチャし、
sed -i -e "s/.*\(extra_star_job_inlist2_name\).*/\1 = '$controls'/i" "$MESA_INLIST"
(他のコマンドもsed
似ています。)
式の前に一重引用符を使用するには、sed
次のようにします。
sed -i -e 's/.*\(extra_star_job_inlist2_name\).*/\1 = '"'$controls'"'/i' "$MESA_INLIST"
もう1つの最適化は、2つの呼び出しをsed
1つにまとめることです。
sed -i -e "s/.*\(extra_star_job_inlist2_name\).*/\1 = '$controls'/i" \
-e "s/.*\(extra_controls_inlist2_name\).*/\1 = '$controls'/i" "$MESA_INLIST"