입력 파일을 편집하기 위해 쉘 스크립트를 작성하려고 합니다. 입력 파일의 데이터 구조는 다음과 같습니다.
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
이것은 분리된 필드로 구성된 입력 라인을 처리합니다 :
. 두 번째 필드가 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
( 두 번째 열 값에 대한 테스트를 위해 값의 공백을 옮겼습니다 .)
스크립트 제안(입력 파일의 정적 파일 경로를 사용합니다.산출수정된 데이터):
#!/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"/"
임무 완료.