저는 쉘 스크립팅이 필요한 연구 프로젝트를 진행 중입니다. 프로그래밍 경험은 있지만 경험은 거의 없습니다. 문제의 파일은 다음과 같습니다.
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
두 번째 파일의 입력을 변경하기 위해 이 파일을 빌려왔습니다 /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가 텍스트를 찾고 바꾸는 스트림 편집기라는 것을 알고 있으며 이것이 두 번째 파일에 대한 나의 목표입니다. 그러나 -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
.
- 두 개의 빈 문자열이 있습니다.
- 확장은
$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"
또 다른 최적화는 두 호출을 sed
하나로 결합하는 것입니다.
sed -i -e "s/.*\(extra_star_job_inlist2_name\).*/\1 = '$controls'/i" \
-e "s/.*\(extra_controls_inlist2_name\).*/\1 = '$controls'/i" "$MESA_INLIST"