다음과 같은 샘플 입력 파일이 있습니다.
Apple Orange Gold Silver Spoon Apple Orange Gold
Apple
Apple Orange
Apple Orange
Mango Gold Silver Spoon Apple Orange
15~20번째 위치가 공백인지 확인한 다음 이를 문자열로 바꿔야 합니다 Silver
. 또한 50~70위의 콘텐츠를 완전히 교체해야 합니다.xxxxxxxxxxxxxxxxxxxxx
답변1
더 작은 행을 처리하는 방법에 따라(위의 설명 참조) sed
해결책은 다음과 같습니다.
sed -e '/^.\{14\} \{6\}/s/^\(.\{14\}\) \{6\}/\1Silver/' \
-e '/^.\{49\}./s/^\(.\{49\}\)\(.\{1,21\}\)\?\(.*\)\?/\1xxxxxxxxxxxxxxxxxxxxx\3/'
그리고 더 깨끗하고 오류가 덜 발생하는 GNU awk
버전은 다음과 같습니다.
awk '
BEGIN { FIELDWIDTHS = "14 6 29 21 999" ; OFS = "" }
$2 == " " { $2 = "Silver" }
$4 != "" { $4 = "xxxxxxxxxxxxxxxxxxxxx" }
{ print }
'
설명하다:
1.) sed:이 sed
명령은 두 개의 독립적 대체로 구성됩니다. 첫 번째는 "Silver" 사례를 처리하고 두 번째는 "xxx..." 사례를 처리합니다. 교체 형태 sed
는 다음과 같습니다.
/pattern/s/pattern2/replacement/
첫 번째 패턴이 일치하면 해당 대체가 수행되고 해당 행의 경우 두 번째 패턴이 대체 표현식으로 대체됩니다. 세부 사항은 sed
일반적으로 비밀스럽습니다.
.
- 어떤 캐릭터라도
\{14\}
- 이전 하위 표현식을 반복합니다(여기서는 14번).
\(expr\)
- 대체 문자열에서 등으로 참조할 수 있는 하위 표현식 \1
. \2
여기서 실제 숫자는 n번째 대괄호 표현식으로 정의됩니다.
\?
- 이전 하위 표현식이 선택적 부분임을 지정합니다.
2.) 어크:프로그램은 이 섹션을 한 번 실행하고 awk
해당 왼손 조건이 true인 경우에만 BEGIN
데이터 파일의 각 줄의 후속 섹션과 해당 오른손 작업을 실행합니다.{...}
FIELDWIDTHS
$i
- 각 필드가 (일부 필드 번호 i의 경우)로 처리될 수 있도록 입력 행의 데이터 필드 너비를 지정합니다.
OFS=""
- 빈 문자열, 출력 필드에는 추가 구분 기호가 없어야 합니다.
$2 == " "
- 두 번째 필드(사양에 따라 FIELDWIDTHS
)에 6개의 공백이 포함된 경우 해당 문자열로 바꿉니다.
$4 != ""
- 네 번째 필드에 데이터가 포함되어 있으면 "xxx..." 문자열로 바꿉니다.
{ print }
- 한두 번의 이전 작업에 의해 수정되었거나 수정되지 않은 행을 표시하는 현재 행의 무조건 인쇄
답변2
sed 's/^\(.\{14\}\) /\1Silver/
s/^\(.\{49\}\).\{20\}/\1xxxxxxxxxxxxxxxxxxxxx/
' <infile >outfile
네, 제 생각에는요.
답변3
Perl을 사용하여 21자 미만의 문자를 포함하는 행(첫 번째 대체의 경우)과 70자 미만의 문자를 포함하는 행(두 번째 대체의 경우)을 삭제해야 한다고 가정합니다.
< inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile
21자 미만의 문자를 포함하는 행(첫 번째 대체의 경우)과 70자 미만의 문자를 포함하는 행(두 번째 대체의 경우)을 먼저 공백으로 채워야 한다고 가정하면 awk
+Perl을 사용하십시오.
< inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile
명령 #1 실패:
< inputfile
: 콘텐츠를 's'inputfile
로 리디렉션합니다.perl
stdin
-p
: Perl이 이 줄을 인쇄하도록 강제합니다.-e
: Perl이 인수로부터 프로그램 라인을 읽도록 강제합니다.> outputfile
perl
:컨텐츠를stdout
다음으로 리디렉션합니다.outputfile
명령 #2 분할:
< inputfile
inawk
: 콘텐츠를 's'inputfile
로 리디렉션합니다.awk
stdin
{printf "%-70s", $0}
: 줄의 문자 수가 70개가 될 때까지 각 줄을 공백으로 채웁니다.|
:awk
파이프 로stdout
연결됨perl
stdin
-p
: Perl이 이 줄을 인쇄하도록 강제합니다.-e
: Perl이 인수로부터 프로그램 라인을 읽도록 강제합니다.> outputfile
perl
:컨텐츠를stdout
다음으로 리디렉션합니다.outputfile
대체 #1 분석:
s
: 교체를 수행하도록 어설션/
: 검색 모드 시작^
: 줄의 시작 부분과 일치합니다.(
: 캡처 그룹 시작.{14}
: 14번 나타나는 임의의 문자와 일치)
: 그룹 캡처 중지{6}
: 6번 등장하는 캐릭터와 일치
/
: 검색 모드 중지/교체 모드 시작$1
: 캡처된 그룹으로 대체됨Silver
Silver
: 문자열 추가/
: 교체 모드 중지
대체 #2 분석:
s
: 교체를 수행하도록 어설션/
: 검색 모드 시작^
: 줄의 시작 부분과 일치합니다.(
: 캡처 그룹 시작.{49}
: 모든 문자의 49개 항목과 일치합니다.)
: 그룹 캡처 중지.{21}
: 21번 등장하는 임의의 문자와 일치/
: 검색 모드 중지/교체 모드 시작$1
: 캡처된 그룹으로 대체됨xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxx
: 문자열 추가/
: 교체 모드 중지
예제 출력:
:~/tmp$ cat inputfile
Apple Orange Gold Silver Spoon Apple Orange Gold
Apple
Apple Orange
Apple Orange
Mango Gold Silver Spoon Apple Orange
~/tmp$ < inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple OrangeSilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxxld
Apple
Apple Orange
Apple OrangeSilver
Mango SilverGold Silver Spoon Apple Orange
~/tmp$ < inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple OrangeSilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxxld
Apple Silver xxxxxxxxxxxxxxxxxxxxx
Apple OrangeSilver xxxxxxxxxxxxxxxxxxxxx
Apple OrangeSilver xxxxxxxxxxxxxxxxxxxxx
Mango SilverGold Silver Spoon Apple Oxxxxxxxxxxxxxxxxxxxxx
~/tmp$