아래와 같이 데이터가 포함된 대용량 파일(2GB 이상)이 있습니다.
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,E:,23432,34534,45345,324
E:
여기에서는 네 번째 열에서 공백이 발견되는 모든 위치를 바꿔야 ""
하지만 나중에 문자열을 찾을 때마다 E:
그대로 유지되어야 합니다.
예상되는 출력은 다음과 같습니다.
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,,23432,34534,45345,324
답변1
귀하의 구문은거의옳은. 에서 문자열 동일성을 테스트하려면 awk
이중 등호를 사용하십시오: ==
. 도착하다값을 지정하다, 단일 등호를 사용합니다.
따라서 이것을 사용하면 if ($4 == "E:")
원하는 결과를 얻을 수 있습니다.
전체 명령은 다음과 같습니다. 사용한 명령과 문자 차이가 하나뿐이라는 점에 유의하세요. 이것이 유일한 실수입니다.
awk -F , '{ if ($4 == "E:") $4="";}1' OFS=, data.final
몇 가지 다른 구문과 다른 접근 방식을 보여주기 위해 다음 버전은 완전히 동일합니다.
awk -F, -v OFS=, '$4 == "E:" { $4 = "" }; 1' data.final
awk 'BEGIN { FS=OFS="," }; $4 == "E:" { $4 = "" }; {print}' data.final
awk -F, -v OFS=, '{sub( /^E:$/, "", $4); print}' data.final
위 사항에 대한 참고사항:
- 전체 코드 블록이 단지 if/then인 경우 조건을 코드 블록의 필터로 사용할 수 있습니다. 따라서 다음
$4 == "E:" {$4 = ""}
과 완전히 동일합니다.{if ($4 == "E:") {$4 = ""}}
- "then" 문이 하나만 있는 경우에도 코드 블록에 "then" 문을 포함하는 것이 좋습니다
if ($4 == "E:") {$4 = ""}
.if ($4 == "E:") $4 = "";
-F
값 세트는 첫 번째 파일의 첫 번째 줄을 고려하기 전에 모든 변수의 값을 설정하는 데 사용될FS
수 있습니다. (아마도 알고 계실 것입니다.) 블록을 사용하여 동일한 작업을 수행할 수도 있습니다. 스크립트가 자체 포함되기를 원할 때 이 점을 알아두는 것이 좋습니다.-v
awk
BEGIN
awk
1
line in을 인쇄하는 이유는 항상 true로 평가되는 조건(필터)이고, 필터에 코드 블록이 첨부되지 않은 경우 기본 동작은awk
to 이기 때문입니다. 따라서 그 자체로는 or 또는 just와 동일합니다.awk
print $0
1
1 {print}
1 {print $0}
{print}
sub
마지막 변형에서는 정규식(문자열의 시작, 문자열의 끝)을 in 으로 바꾸는 함수를 사용했습니다 ./^E:$/
E:
""
$4
sub
함수는 대체된 횟수(1 또는 0, 여러 대체를 만드는 경우)를 반환 하므로 함수 결과에 1을 추가하여 항상 참인 패턴이 있는지 확인하여 교체가 인쇄되는지 여부를 확인하여 이 문제를 해결할 gsub
수 있습니다. sub
결과 라인. 다음은 골프 버전의 코드입니다. 나중에 유지 관리할 스크립트에 코드를 넣는 경우 초보자에게는 권장되지 않습니다.
awk -F, -v OFS=, 'sub(/^E:$/,"",$4)+1' data.final
:)
답변2
그리고 sed
:
sed -r 's/^([^,]+,[^,]+,[^ ]+,)E:(,)/\1\2/' file.txt
쉼표로 구분된 네 번째 필드에 다음 항목만 포함된 경우 해당 필드는 비어 있습니다 E:
.
예:
% cat file.txt
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,E:,23432,34534,45345,324
% sed -r 's/^([^,]+,[^,]+,[^ ]+,)E:(,)/\1\2/' file.txt
12,324,32342,E:fsdsf,23432,34534,45345,324
13,3224,342,E:werwefsdsf,23432,34534,45345,324
121,3244,33442,,23432,34534,45345,324
답변3
파일 이름이 이라고 가정하면 file
다음을 시도해 볼 수 있습니다.
while read -r line;
do
var="$(echo "$line" | cut -d ',' -f 4)";
if [[ "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/''/g ;
else echo "$line";
fi;
done < file
또는:
while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/''/g ; else echo "$line";fi; done < file
설명하다:
while read -r line;
파일을 한 줄씩 읽기var="$(echo "$line" | cut -d ',' -f 4)";
4번째 위치의 문자열을,
변수로 분리합니다.var
if [[ && "$var" = "E:" ]]; then echo "$line" | sed s/"$var"/' '/g ;
$var
문자열이 있으면 공백 으로 바꿉니다E:
.sed s/"$var"/''/g ;
""
else echo "$line";
그렇지 않으면 행을 그대로 인쇄합니다.
예산출(질문에서 예상한 대로):
file
:$ cat file 12,324,32342,E:fsdsf,23432,34534,45345,324 13,3224,342,E:werwefsdsf,23432,34534,45345,324 121,3244,33442,E:,23432,34534,45345,324
실행 명령:
$ while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" |sed s/"$var"/' '/g ; else echo "$line";fi; done < file 12,324,32342,E:fsdsf,23432,34534,45345,324 13,3224,342,E:werwefsdsf,23432,34534,45345,324 121,3244,33442,,23432,34534,45345,324
>> file2
|tee file2
명령 끝에서 또는 를 사용하여 출력을 파일로 리디렉션 할 수도 있습니다 .
while read -r line; do var="$(echo "$line" | cut -d ',' -f 4)"; if [[ "$var" = "E:" ]]; then echo "$line" |sed s/"$var"/' '/g ; else echo "$line";fi; done < file | tee file2