다음과 같은 일부 자리 표시자가 있는 Linux 시스템에 일부 파일이 있습니다.
테스트.txt:
This is a line with <VARIABLE1>@<VARIABLE2>.
This is a line with <VARIABLE3>.
This is a line with <VARIABLE_UNKNOWN>.
This is another line contains a<b.
이 파일을 다음과 같이 변경하고 싶습니다.
This is a test line with $VARIABLE1@$VARIABLE2.
This is a test line with $VARIABLE3.
This is a test line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
로 끝나는 모든 변수에는 <>
대문자, 숫자 및 밑줄만 포함됩니다.
다음 방법을 사용할 수도 있었지만 a<b
대신 a$b
.
file_contents=$(<$file_path)
file_contents=${file_contents//</$}
file_contents=$(echo "$file_contents" | tr -d '>')
echo "$file_contents" > test.txt
sed
디버깅하기가 매우 어려워지는 복잡한 명령을 사용하지 않으려고 노력하고 있습니다 . 이 목표를 어떻게 달성할 수 있나요?
답변1
이는 개별 라인을 간단히 교체하는 것이므로 이를 수행하는 sed 명령은 복잡하지 않습니다.
$ sed -E 's/<([[:upper:][:digit:]_]+)>/$\1/g' file
This is a line with $VARIABLE1@$VARIABLE2.
This is a line with $VARIABLE3.
This is a line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
-E
또는 sed에 POSIX sed가 없는 경우 :
sed 's/<\([[:upper:][:digit:]_]\{1,\}\)>/$\1/g' file
귀하의 sed가 POSIX와 호환되지 않는 경우새 것을 사다하지만 이 특정 작업을 위해 다음을 수행할 수 있습니다.
sed 's/<\([A-Z0-9_][A-Z0-9_]*\)>/$\1/g' file
~처럼@chrisdavies가 지적했습니다.<VAR1>27
, 그러나 그것은 아마도 당신이 실제로 얻으려고 노력해야 할 결과가 아닐 것입니다 . 결과적으로 $VAR127
다음 중 하나를 실제로 목표로 삼아야 합니다.
$ sed -E 's/<([[:alnum:]_]+)>/${\1}/g' file
This is a line with ${VARIABLE1}@${VARIABLE2}.
This is a line with ${VARIABLE3}.
This is a line with ${VARIABLE_UNKNOWN}.
This is another line contains a<b.
$ sed -E 's/<([[:alnum:]_]+)>/"${\1}"/g' file
This is a line with "${VARIABLE1}"@"${VARIABLE2}".
This is a line with "${VARIABLE3}".
This is a line with "${VARIABLE_UNKNOWN}".
This is another line contains a<b.
출력으로 무엇을 하려는지에 따라 다릅니다.
FWIW 일반적으로 사람들은 텍스트에 자리 표시자 문자열이 있을 때 이를 대체하지 않습니다.이름쉘 변수는 다음으로 대체됩니다.콘텐츠쉘 변수입니다. 그렇지 않으면 처음에 쉘 변수 이름으로 텍스트를 생성할 수 있는데 텍스트에 자리 표시자를 사용하는 것이 무슨 의미가 있을까요?
답변2
< >
문제가 " 하나 이상의 대문자, 숫자 및 밑줄이 포함되어 있지만 < >
자체 내에 포함되어 있지만 "로 $
대체 된 모든 문자열을 변환하고 싶습니다"로 공식화할 수 있는 경우 < >
다음을 수행할 수 있습니다.
$ perl -pe 's/<([A-Z\d_]+)>/\$$1/g' file
This is a line with $VARIABLE1@$VARIABLE2.
This is a line with $VARIABLE3.
This is a line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
이는 -pe
"입력 파일을 한 줄씩 읽고, 주어진 스크립트를 적용하고 -e
, 각 줄을 인쇄한다"는 의미입니다. 그런 다음 대체 연산자( s/OLD/NEW/
)를 g
플래그와 함께 사용하여 해당 행의 모든 항목을 대체합니다. 마지막으로 정규식은 문자 <
뒤에 하나 이상의 +
대문자 ASCII 문자( A-Z
), ASCII1 10진수( \d
) 또는 _
후행 밑줄( )이 오는 문자를 찾습니다 >
. 이제 패턴이 대괄호( ) 안에 있으므로 이를 "캡처"했으며 교체에서 ([A-Z\d_]+)
참조 할 수 있습니다. $1
따라서 일치 항목을 $
( 이스케이프해야 함 \$
)로 바꾼 다음 일치 항목을 다음으로 바꿉니다 \$$1
.
적어도 $PERL_UNICODE
이 경우에는 환경 변수가 설정되지 않은 한 다른 유형의 십진수와 일치합니다. 이 a
플래그를 연산자에 사용하여 s///
0123456789만 일치하는지 확인하거나 또는 또는 \d
로 바꾸십시오.0-9
0123456789
답변3
사용행복하다(이전 Perl_6)
~$ raku -pe 's:g/ \< ( <[A..Z0..9_]>+ ) \> /\$$0/;' file
다시 말하지만 이것은 @terdon의 뛰어난 Perl 답변을 거의 직접 번역한 것입니다.
기쁨에,
- 정규식 수정자(예: 전역) 는 "대체 전역" 형식을
g
제공하기 위해 매처의 머리 부분에 콜론 다음에 배치됩니다 .s:g///
<[ ... ]>
인식 필드 내에서 꺾쇠 괄호로 묶인 대괄호를 사용하여 사용자 정의 문자 클래스를 만듭니다. 대괄호는 정규식 원자 및/또는 속성을 함께 그룹화하기 위해 단독으로 사용됩니다(아래 예 참조).- 문자 범위는 (예를 들어) 또는
..
와 같이 이중 점으로 지정됩니다 .A..Z
0..9
\<
Raku는 영숫자가 아닌 밑줄이 아닌 모든 문자를 인용하거나(백슬래시) 이스케이프해야 정규 표현식의 리터럴로 이해되도록 이스케이프 규칙을 단순화하므로 인식 필드에서 and 를 사용해야 합니다 .\>
- 숫자 캡처는 Perl에서와 같이 괄호를 통해 Raku에서 지정되지만 이러한 숫자 캡처는
$0
대체 필드 내에서 시작하고 사용해야 합니다. - OP는 잘못된 대체를 언급하고 있으며 일반적으로 특정 문자에 대해 백슬래시를 요구하는 것은 문제가 될 수 있습니다. 도움을 주기 위해 Raku는 위의 대체 항목 (예: 보간된 문자열)을 작성할 수
{...}
있도록 대체 필드에 코드 블록을 사용할 수 있도록 허용합니다.{"\$$0"}
출력에 대해 간단한 수학 연산(합계 등)을 수행하는 데 매우 유용합니다.
입력 예:
This is a line with <VARIABLE1>@<VARIABLE2>.
This is a line with <VARIABLE3>.
This is a line with <VARIABLE_UNKNOWN>.
This is another line contains a<b.
예제 출력:
This is a line with $VARIABLE1@$VARIABLE2.
This is a line with $VARIABLE3.
This is a line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
마지막으로 @terdon은 정규식 시스템과 관련된 모든 문제에 대한 좋은 개요를 제공하여 정확하게 이해해야 합니다.숫자, 즉 ASCII 숫자입니까, 아니면 유니코드 숫자입니까?
Raku는 "유니코드 지원" 언어라는 점에 자부심을 갖고 있으며, 하단의 첫 번째 링크에서 Raku 정규식에 대한 광범위한 유니코드 문자 클래스 목록을 찾을 수 있습니다. 그러므로 라쿠의 \d
숫자 약어는유니코드 숫자를 포함합니다.위와 같이 숫자를 열거하거나 접속사와 결합된 문자 클래스를 사용하여 다음과 같이 숫자를 ASCII 숫자로 0..9
하위 집합/제한할 수 있습니다 .\d
<:ASCII>
&&
[<:ASCII> && \d]
~$ raku -pe ' s:g/ \< ( [ [<:ASCII> && \d] | <:Lu> | _ ]+ ) \> /\$$0/;' file
위는 <:Lu>
"Letters-uppercase" 유니코드 문자 클래스입니다. 원하는 경우 <:ASCII>
동일한 방법을 사용하여 "ASCII 대문자"로 부분 집합할 수 있습니다(또는 더 간단하게 위의 대괄호를 재정렬하여 재그룹화).
https://docs.raku.org/언어/regexes#Unicode_properties
https://www.unicode.org/terminology/digits.html
https://docs.raku.org/언어/regexes#접속사:_&&
https://docs.raku.org/언어/regexes
https://raku.org
답변4
사용 gawk
:
$ awk '{print gensub(/<([[:alnum:]_]+)>/, "$\\1", "g")}' file
# Or
$ awk '{print gensub(/<(\w+)>/, "$\\1", "g")}' file
This is a line with $VARIABLE1@$VARIABLE2.
This is a line with $VARIABLE3.
This is a line with $VARIABLE_UNKNOWN.
This is another line contains a<b.
gensub() 함수에서 대괄호 as를 사용하여 하위 패턴을 기억 captured group
하고 나중에 as를 사용하여 참조 할 수 있습니다 backreference
.\n
.
GNU awk
매뉴얼 에서 :
젠섭()사용할 수 없는 추가 기능을 제공합니다.아들()또는gsub(): 대체 텍스트에 정규 표현식의 구성요소를 지정하는 기능. 이는 정규식에서 괄호를 사용하여 구성 요소를 표시한 다음 지정함으로써 수행됩니다.'\N'대체 텍스트에서질소1에서 9 사이의 숫자입니다.