두 개의 기억된 패턴을 인쇄하고 그 사이에 영숫자가 아닌 문자만 인쇄합니다.

두 개의 기억된 패턴을 인쇄하고 그 사이에 영숫자가 아닌 문자만 인쇄합니다.

저는 Debian 11에서 GNU sed 4.7을 사용하고 있습니다.

여러 줄이 있는 파일이 있는데, 모든 줄에는 줄 시작 부분에 중괄호로 묶인 첫 번째 문자열이 있고, @줄 끝에 있는 문자의 마지막 문자열이 있으며, 줄 사이에 영숫자, 구두점 및 기타 문자가 포함된 문자열이 있습니다. 위의 문자열 터미널 문자열입니다.

첫 번째 문자열과 마지막 문자열 전체를 표시하는 출력을 생성하고 싶습니다.오직중간 문자열에 알파벳이 아닌 문자가 있으므로 다음과 같습니다.

./file다음 콘텐츠가 포함되어 있습니다:

{string-no1}middle@string-no2@
{AAAAAAAAAA}1,a.B£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:3m?J@@@@@@@@@@@@

...출력을 보고 싶습니다.

{string-no1}@string-no2@
{AAAAAAAAAA},.£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:?@@@@@@@@@@@@

나는 시도했다:

sed 's/\({[^}]*}\)[^a-zA-Z0-9]*\(@[^@]*@\)/\1\2/' ./file

...하지만 이는 작동하지 않으며 다음과 같은 경우에도 작동하지 않습니다.

sed 's/\({[^}]*}\)[[:punct:]]*\(@[^@]*@\)/\1\2/' ./file`

...도 아니다:

sed '/}/,/@/ s/[a-zA-Z0-9]*//' ./file

나는 grymoire와 StackExchange에 도움을 요청해 보았지만 일반적으로 모든 문제를 해결해 주었지만 이 문제는 정말 마음에 와 닿았습니다. 누구든지 도와줄 수 있나요?

답변1

이는 에서는 수행하기 어렵지만 sed(각 입력 줄의 세 가지 다른 부분으로 서로 다른 작업을 수행해야 하기 때문입니다. s///아무것도 하지 않고, 수정하고, 아무것도 수행하지 않음) 에서는 수행하기 쉽습니다 perl.

$ perl -lne '($first,$middle,$last) = (/({[^}]*})([^@]*)(@.*)/);
             $middle =~ s/[[:alnum:]]+//g;
             print $first, $middle, $last' file 
{string-no1}@string-no2@
{AAAAAAAAAA},.£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:?@@@@@@@@@@@@

먼저 정규식을 사용하여 입력 줄의 첫 번째, 중간, 마지막 부분을 적절한 이름의 변수로 추출합니다. 그런 다음 $middle에서 모든 영숫자 문자를 제거합니다. 그런 다음 인쇄합니다.

답변2

중위 문자열(중간 비트)에 영숫자와 영숫자가 아닌 문자가 혼합되어 있으므로 시도가 작동하지 않습니다. s/[[:alnum:]]//g접두사 및 접미사 문자열에 대해 동일한 작업을 수행하지 않고 중위어를 사용하여 처리해야 합니다 .

그러므로 당신은 필요합니다격리변수의 중위 문자열 또는 편집 버퍼의 경우 sed영숫자 문자를 제거하는 작업을 적용한 다음 접두사 및 접미사 문자열을 결과에 다시 적용합니다.

sed편집 스크립트를 사용하십시오 :

h
s/^{[^}]*}//
s/@[^@]*@$//
s/[[:alnum:]]//g
G
s/^\(.*\)\n\({[^}]*}\).*\(@[^@]*@\)$/\2\1\3/

시험:

$ sed -f script file
{string-no1}@string-no2@
{AAAAAAAAAA},.£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:?@@@@@@@@@@@@

마지막 줄의 중위 문자열은 실제로는

&:?@@@@@@@@@@

접미사는

@@

주석이 달린 스크립트:

# Remember the original line in the hold space.
h

# Remove the prefix and the suffix strings.
# The prefix is "{...}" at the start of the line.
# The suffix is "@...@" at the end of the line.
# The interior of these strings does not contain
# the respective string terminator.
s/^{[^}]*}//
s/@[^@]*@$//

# We are left with the isolated infix portion of the
# original line. Remove the alphanumerical characters
# from this. This creates the final infix string.
s/[[:alnum:]]//g

# Append the original line from the hold space to the end of
# the infix string with a newline (\n) as the delimiter.
G

# Match the modified infix, prefix, and suffix only, and
# substitute the entire buffer with these parts in the
# correct order.
s/^\(.*\)\n\({[^}]*}\).*\(@[^@]*@\)$/\2\1\3/

답변3

를 사용하면 perl다음 작업도 수행할 수 있습니다.

perl -lne 'print /^\{.*?\}|@.*|\W/g' < your-file

\Walnum 및 underscore를 제외한 문자와 일치합니다. 기본적으로 ASCII 문자만 일치됩니다. 밑줄을 포함하려면 [^a-zA-Z0-9]또는 로 바꾸면 됩니다.[^[:alnum:]]

다음을 사용하여 루프에서 sed첫 번째 와 첫 번째 }사이의 alnum 문자를 제거할 수 있습니다.@

sed -e :1 -e 's/^\([^}]*}[^@]*\)[[:alnum:]]/\1/; t1' < your-file

for는 로케일로 분류되고 텍스트는 로케일의 문자 집합에 따라 디코딩되는 반면, 기본적 sed으로 텍스트는 iso8859-1로 인코딩된 것처럼 해석되며 ASCII 숫자만 일치합니다(그렇게 하지 않는 한). 플래그 추가 ).[[:alnum:]]perl[[:alnum:]]/u

로케일을 ( )로 수정하면 유사 동작을 얻을 수 있고, perl로케일 문자 집합에 따라 문자를 디코딩하고 로케일 분류 설정 대신 유니코드 속성을 사용하여 문자를 분류하는 옵션을 추가하면 유사 동작으로 s를 얻을 수 있습니다. .sedCLC_ALL=C sed...sedperl-Mopen=locale

답변4

awk정규식을 사용하지 않으려면 다음과 같은 방법을 사용하세요.

cat file.txt
{string-no1}@string-no2@
{AAAAAAAAAA},.£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:?@@@@@@@@@@@@

awk댓글은 내부적으로 처리가 가능 하므로 복사붙여넣기 시 남길 수 있습니다.

awk '
   BEGIN{                             # sets '}' as field separator
        FS="}"                        # splitting text into 2 fields 
   }                                  
   { 
    i=index($2,"@")                   # finds index position of '@'
    str1=$1                           # str1 = 1st field
    str2=substr($2,0,i-1)             # str2 = 2nd field until first '@' 
    str3=substr($2,i,length($2))      # str3 = 2nd field from '@' till end
    gsub(/[[:alnum:]]/,"",str2)       # replaces alphan in str2 with blanks
    print str1"}"str2 str3            # combines str1,str2,str3 and prints

}' file.txt

산출:

{string-no1}@string-no2@
{AAAAAAAAAA},.£@ZZZZZZZZZZ@
{GGGGGGGGGG}&:?@@@@@@@@@@@@

관련 정보