일부 텍스트를 처리해야 하는 쉘 스크립트를 작성 중인데 다음과 같은 텍스트가 표시됩니다.
read build { file1 file2 file3 }
check build { file2 file3 file4 }
read build { file4 file5 file6 }
모든 파일 앞에 텍스트를 추가하고 싶습니다. 즉, "읽기 빌드" 줄의 괄호 사이에 포함된 단어를 의미합니다. 이를 달성하는 가장 좋은 아이디어는 무엇이라고 생각하십니까? 결과는 다음과 같아야 합니다.
read build { MY_ADDED_WORDfile1 MY_ADDED_WORDfile2 MY_ADDED_WORDfile3 }
check build { file2 file3 file4 }
read build { MY_ADDED_WORDfile4 MY_ADDED_WORDfile5 MY_ADDED_WORDfile6 }
줄을 잡아서 배열로 구문 분석하고 이 "파일" 문자열을 추가하려는 단어와 연결하려고 합니다. 하지만 이것이 "스마트" 솔루션이라고 생각하지 않습니다. 당신의 도움을 주셔서 감사합니다.
입력 파일은 다음과 같습니다.
set build { file1 file2 file3 file4 }
check $build
read build -new -f $build
read build -new -f { fileA fileB fileC fileD }
set build {file5 file6 file7 }
read build -old -f $build
read build -old -f { fileX fileZ fileD }
check_that_building
출력은 다음과 같아야 합니다.
set build { file1 file2 file3 file4 }
check $build
read build -new -f $build
read build -new -f { MY_ADDED_WORDfileA MY_ADDED_WORDfileB MY_ADDED_WORDfileC MY_ADDED_WORDfileD }
set build {file5 file6 file7 }
read build -old -f $build
read build -old -f { MY_ADDED_WORDfileX MY_ADDED_WORDfileZ MY_ADDED_WORDfileD }
check_that_building
왼쪽 괄호 앞에는 항상 공백이 있지만 오른쪽 괄호 앞에는 공백이 있을 수 있지만 항상 그런 것은 아닙니다. 가능한 상황:
read build -old -f { fileX fileZ fileD }
read build -old -f {fileX fileZ fileD }
read build -old -f { fileX fileZ fileD}
read build -old -f {fileX fileZ fileD}
답변1
sed
입력에 전혀 나타나지 않는 것으로 알려진 문자가 하나 이상 있다고 가정하지 않고는 이 작업을 수행하는 방법을 즉시 알아낼 수 없습니다. 나는 그것이 #
입력(또는 당신이 추가한 단어)에 결코 나타나지 않을 것이라고 가정합니다. 이것은 작동하는 것 같습니다:
sed '/read build/ {
s/{/{ /
: fruit
s/\({.*\) \([^}# ][^ ]*\)/\1#MY_WORD\2/
t fruit
s/#/ /g
s/{ /{/
}'
이를 포함하는 줄에서는 read build
그 뒤에 공백이 삽입됩니다 {
. 그런 다음 {
단어 뒤와 단어(파일 이름일 수 있음) 바로 앞의 공백을 검색합니다 . 공백을 바꾸고 #
단어를 삽입한 다음 다시 돌아가서 더 많은 내용을 찾습니다. ( fruit
임의의 루프 레이블입니다.) 모든 문자를 찾으면 #
모든 문자를 다시 공백으로 변환하고 삽입한 공백(뒷면 {
)을 제거합니다.
#
입력에 나타나지 않는 입력에 대한 정보 외에 다음과 같은 정보도 가정됩니다.
}
각 줄의 공백이 아닌 마지막 문자입니다read build
.- 공백은 공백일 뿐입니다. 탭이 없습니다.
존재하다 awk
:
awk '/read build/ {
in_braces=0
for (i = 1; i <= NF; i++) {
if ($i == "{") in_braces=1
else if (substr($i,1,1) == "{") {
$i = "{MYWORD" substr($i,2)
in_braces=1
}
else if ($i == "}") in_braces=0
else if (in_braces) $i = "MY_WORD" $i
}
}
{ print }'
각 read build
행에 대해 해당 행의 모든 단어(필드)를 반복합니다. 상태 변수( )를 사용하여 a와 a 사이에 in_braces
있는지 추적합니다 . 그렇다면 추가한 단어로 시작하도록 각 단어를 수정합니다. 이는 약간 다른 두 가지 상황을 처리해야 한다는 점에 유의하세요.{
}
- 만약에 한마디예
{
, 모든 후속 단어 수정을 시작하도록 플래그를 설정하고 - 만약에 한마디다음으로 시작됨
{
, 실제로는 형식의 복합이므로 수정하세요.{fileX
그것예{
, 추가된 단어와fileX
파일 이름. 또한 모든 후속 단어를 수정하기 위한 플래그를 설정합니다.
이는 탭 문자를 단어 구분 기호로 허용하지만 공백을 단일 공백으로 축소하는 단점이 있습니다. 예를 들어 다음을 입력합니다.
read build { file1 file2 file3 }
출력을 생성합니다
read build { MY_WORDfile1 MY_WORDfile2 MY_WORDfile3 }
게다가 이는 다음과 같이 가정합니다.
- the는
{
단어의 시작 부분에 있습니다(즉, 앞에 공백이 옵니다). }
각 줄의 공백이 아닌 마지막 문자 또는read build
별도의 단어(예: 앞뒤에 공백 포함)
예를 들어, 여러 세트의 중괄호를 허용합니다.
read build { file1 file2 file3 } text to be left alone { file4 file5 file6 }