저는 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
\W
alnum 및 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를 얻을 수 있습니다. .sed
C
LC_ALL=C sed...
sed
perl
-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}&:?@@@@@@@@@@@@