v
파일에서 삭제하고 싶은 값의 배열이 있습니다 f
. f
NUL로 구분됩니다. 어떻게 진행하나요? sd
사용해 봤으나쓸모 없는.
예:
나는 이 파일을 가지고 있습니다 :
# cat -v $attic
^@this is 1.
this is 2.
this is 3.
^@hi
^@blue boy
이 변수는 다음 $i
과 같습니다.
# cat -v <<<"$i"
this is 1.
this is 2.
this is 3.
이 파일에서 삭제하라는 명령을 실행하고 싶은데 $i
결과는 다음과 같습니다.
^@hi
^@blue boy
이것을 시도했지만 FROM="$i" perl -pi -e 's/\0\Q$ENV{FROM}\E//g' "$attic"
여러 줄이 있으면 작동하지 않습니다 $i
. 시도해 보았 FROM="$i" perl -pi0 -e 's/\0\Q$ENV{FROM}\E//g' "$attic"
으나 아무 소용이 없었습니다.
답변1
당신이 언급했으므로 zsh
다음과 같이 할 수 있습니다.
zmodload zsh/mapfile
mapfile[$attic]=${(pj:\0:)"${(0@)mapfile[$attic]}":#$i}
$mapfile
모듈 내부에는zsh/mapfile
파일 이름을 해당 내용에 매핑하는 특수 연관 배열이 있습니다."${(0@)var}"
: NUL로 분할합니다$var
(@
예: 내부 따옴표로 빈 요소를 유지합니다"$@"
).${array:#pattern}
. 패턴과 일치하는 요소를 제거합니다. 여기에 있는 내용은 문자 그대로 받아들여지므로 이를 모드로 처리$i
해야 합니다 (또는 옵션을 활성화해야 합니다).$~i
globsubst
${(j:string:)array}
: 배열의 요소를 로 연결합니다string
. 를 사용하여p
NUL\0
로 변환하세요. (0
위의 매개변수 확장 플래그도 작성할 수 있습니다ps:\0:
.)
다음과 같은 것을 얻을 수 있습니다 perl
.
FROM=$i perl -0lni -e 'print if $_ ne $ENV{FROM}' -- "$attic"
차이점은 perl
아직 NUL이 없으면 끝에 NUL이 추가된다는 것입니다(일반적인 문제 -i
(링크 깨짐, 모든 메타데이터를 유지하지 않음...)와 함께).
더 가까운 내용은 다음과 같습니다.
FROM=$i perl -0777 -F'\0' -pi -e '
$_ = join "\0", grep {$_ ne $ENV{FROM}} @F' -- "$attic"
당신의
FROM="$i" perl -pi0 -e 's/\0\Q$ENV{FROM}\E//g' "$attic"
다음과 같은 이유로 작동하지 않습니다:
- in
-pi0
: (백업 파일 이름 접미사)0
로 간주되는 매개변수-i
- 비록 당신이 그것을 썼다고 해도
-0pi
그것은perl
NUL-을 처리하라고 지시하기 때문에 작동하지 않을 것입니다.종료레코드이므로$_
레코드()의 끝 부분에는 시작 부분이 아닌 NUL이 포함됩니다. 전체 입력을 포함하는 하나의 레코드로 입력을 처리하려면-0777
for를 사용합니다 .perl
답변2
입력 데이터에 따라 파일이 메모리에 들어갈 만큼 작다고 가정하면 다음이 도움이 될 수 있습니다.
$ export i
$ perl -0777 -pe 's/\Q$ENV{i}\E\n?//g' file
hi
blue boy
전체 파일이 메모리에 들어가는 원인은 무엇입니까 -0777
? perl
이는 $ENV{var}
내보낸 환경 변수에 액세스하는 Perl의 방법입니다. 따라서 $ENV{i}
내보낸 변수의 값을 얻게 됩니다 i
. 글로벌 로 s/old/new/g
대체됩니다 . 패턴이 정규식으로 해석되지 않는지 확인하세요 . 마지막으로, 쉘은 명령 대체(예를 들어)의 출력을 배포할 때 변수 끝에서 개행 문자를 먹기 때문에 최종 개행 문자는 실제로 포함되지 않을 수 있습니다 .old
new
\Q
\E
\n?
var=$(printf 'foo\n')
$i
이는 하위 문자열과도 일치합니다. 따라서 파일이 포함되어 i
있으면 삭제되고 남겨질 것 입니다 . 이를 원하지 않으면 다음을 사용할 수 있습니다.foo
foolish
foo
ish
perl -0777 -pe 's/\Q$ENV{i}\E(\n|\b)//g' file
예제를 테스트하십시오( 교체 ^@
후 \0
).
$ cat -v file
^@this is 1.
this is 2.
this is 3.
^@hi
^@blue boy
$ export i="$(printf 'this is 1.\nthis is 2.\nthis is 3.\n')"
$ perl -0777 -pe 's/\Q$ENV{i}\n?\E//g' file
hi
blue boy
물론 이것은 $i
후행 줄 바꿈이 없다고 가정합니다. 하나가 있는지는 모르겠습니다. cat <<<"$i"
없어도 하나 추가할 것이기 때문입니다.
쉘 배열을 사용하여 이 작업을 수행해야 하는 경우 다음을 수행할 수 있습니다.
for i in "${foo[@]}"; do
export i
perl -0777 -i -pe 's/\b\Q$ENV{i}\E(\n|\b)//g' file
done
중요한: -i
위의 예를 참고하세요. 이렇게 하면 파일이 그 자리에서 편집되므로 테스트하기 전에 백업하세요.