1

I am doing a research project that requires shell scripting, which I have almost no experience in, although I do have some programming experience. Here is the file in question:

export OMP_NUM_THREADS=12


read controls
#inlist directory
export MESA_INLIST="/home/nick/mesa-r11701/star/test_suite/rsp_Cepheid_grid/inlist"

I am borrowing this file to change the input of this second file /home/nick/mesa-r11701/star/test_suite/rsp_Cepheid_grid/inlist.

   RSP_mass = 4.165d0
   RSP_Teff = 6050
   RSP_L = 1438.8d0
   RSP_X = 0.73d0
   RSP_Z = 0.007d0

      log_directory='LOGS_1'
      photo_directory='photos_1'

And I want to assign different floats (or integers to concatenate to the 'photos_ and 'LOGS_ strings to change those from LOGS_1 to LOGS_2, for example) to these several variables. Would I write my sed commands like so? I am not asking if this the only way to achieve this, but if this is the one of the correct ways for doing this.

read mass
read Teff
read L
read X
read Z
read d_number


sed -i -e "s/.*\(RSP_mass\).*/\1 = '$mass'/i" "$MESA_INLIST"
sed -i -e "s/.*\(RSP_Teff\).*/\1 = '$Teff'/i" "$MESA_INLIST"
sed -i -e "s/.*\(RSP_L\).*/\1 = '$L'/i" "$MESA_INLIST"
sed -i -e "s/.*\(RSP_X\).*/\1 = '$X'/i" "$MESA_INLIST"
sed -i -e "s/.*\(RSP_Z\).*/\1 = '$Z'/i" "$MESA_INLIST"
sed -i -e "s/.*\(log_directory\).*/\1 = 'LOGS_$d_number'/i" "$MESA_INLIST"
sed -i -e "s/.*\(photo_directory\).*/\1 = 'photos_$d_number'/i" "$MESA_INLIST"

To get context as to why I wrote the sed commands in this particular manner, please refer to the answer of my previous question.

thecep1
  • 31
  • 6

2 Answers2

1

If the output meets your expectations, i.e. no indentation, single quotes around all values and always a space character before and after =, I'd probably make these minor changes:

  • One read command (with -p if supported) for all variables. It's easier to edit all values at once (space/tab separated).
  • One sed call, already mentioned in the previous answer
  • Replace .* with ^[[:blank:]]* to only match spaces or tabs at the beginning of the line
  • Use lowercase variable names for local variables for consistency

read -p "Please enter mass, Teff, L, X, Z, directory number: " mass teff l x z d_number

sed -i \
  -e "s/^[[:blank:]]*\(RSP_mass\).*/\1 = '$mass'/i" \
  -e "s/^[[:blank:]]*\(RSP_Teff\).*/\1 = '$teff'/i" \
  -e "s/^[[:blank:]]*\(RSP_L\).*/\1 = '$l'/i" \
  -e "s/^[[:blank:]]*\(RSP_X\).*/\1 = '$x'/i" \
  -e "s/^[[:blank:]]*\(RSP_Z\).*/\1 = '$z'/i" \
  -e "s/^[[:blank:]]*\(log_directory\).*/\1 = 'LOGS_$d_number'/i" \
  -e "s/^[[:blank:]]*\(photo_directory\).*/\1 = 'photos_$d_number'/i" \
  "$MESA_INLIST"
Freddy
  • 25,565
  • Hi there, what if I want the output to keep the same indentation as the original file and a space character always before and after =? – thecep1 May 18 '20 at 01:35
  • To "catch" the whitespace, move the opening \( to the beginning of the match, i.e. -e "s/^\([[:blank:]]*RSP_mass\).*/\1 = '$mass'/i" \. You're already adding a space character before and after = in your replacement (more consistent than in the input file). – Freddy May 18 '20 at 01:46
  • Thank you so much! – thecep1 May 18 '20 at 01:59
0

I don't think that you want the single quotes around any of the replacement variables other than 'LOGS_$d_number' and 'photos_$d_number' The rest of the variables appear to be numbers, and putting single quotes around them will probably make them into strings which will, at the very best, reduce the speed of your calculations, or (depending on the language you're using) cause a variable type mismatch. I'm presuming that the purpose of the '...d0' subscript is to force the values to be double floats.

Depending on what, exactly you're doing: Rather than reading in the variables as input once the script is running, you can simply specify them as parameters on the command line...

the_script  4.2d1  5000 1300d0 .5d0 .001d0 3

Then your script (named 'the_script', in this case) would start:

mass="$1"
teff="$2"
l="$3"
x="$4"
z="$5"
d_number="$6"

# Simple error checking
if [[ $# -lt 6 ]] ; then
  # print message to stderr with >&2  rather than standard output
  # $0 is the script filename
  echo "$0 : too few variables on the command line. We wanted 6 but got $#." >&2 
  exit 2
fi

You could also have "MESA_INLIST" be a commandline parameter rather than an exported variable.