기본적으로 파일에서 입력 텍스트로 가져 와서 해당 파일에서 한 줄을 제거하고 출력을 동일한 파일로 다시 보내고 싶습니다. 이 선을 따라 가면 더 명확 해집니다.
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > file_name
그러나 이렇게하면 빈 파일이 생깁니다. 이견있는 사람?
답변
bash가 먼저 리디렉션을 처리 한 다음 명령을 실행하기 때문에 그렇게 할 수 없습니다. 따라서 grep이 file_name을 볼 때 이미 비어 있습니다. 그래도 임시 파일을 사용할 수 있습니다.
#!/bin/sh
tmpfile=$(mktemp)
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > ${tmpfile}
cat ${tmpfile} > file_name
rm -f ${tmpfile}
이와 같이 tmpfilemktemp
을 만드는 데 사용 하는 것을 고려 하지만 POSIX가 아니라는 점에 유의하십시오.
답변
이런 종류의 작업 에는 스폰지 를 사용하십시오 . moreutils의 일부입니다.
다음 명령을 시도하십시오.
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | sponge file_name
답변
대신 sed를 사용하십시오.
sed -i '/seg[0-9]\{1,\}\.[0-9]\{1\}/d' file_name
답변
이 간단한 것을 시도하십시오
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | tee file_name
이번에는 파일이 비어 있지 않습니다. 🙂 출력도 터미널에 인쇄됩니다.
답변
동일한 파일에 대한 리디렉션 연산자 ( >
또는 >>
)를 사용할 수 없습니다. 우선 순위가 더 높고 명령이 호출되기 전에 파일을 생성 / 자르기 때문입니다. 그것을 방지하기 위해 다음과 같은 적절한 도구를 사용해야합니다 tee
, sponge
, sed -i
또는 파일 (예에 대한 결과를 쓸 수있는 다른 도구 sort file -o file
).
기본적으로 입력을 동일한 원본 파일로 리디렉션하는 것은 의미가 없으며이를 위해 적절한 내부 편집기 (예 : Ex 편집기 (Vim의 일부))를 사용해야합니다.
ex '+g/seg[0-9]\{1,\}\.[0-9]\{1\}/d' -scwq file_name
어디:
'+cmd'
/-c
-Ex / Vim 명령 실행g/pattern/d
– 전역 (help :g
)을-s
-무음 모드 (man ex
)-c wq
-실행:write
및:quit
명령
당신은 사용할 수 sed
있지만, (이미 다른 답변에서와 같이) 동일을 달성하기 위해 자리에서 ( -i
(유닉스 / 리눅스 사이에 다르게 작동 할 수 있습니다) 표준이 아닌 FreeBSD의 확장은) 기본적으로 그것은이다 의 tream 에드 당사 홈페이지가 아닌 파일 편집기 . 참조 : Ex 모드는 실용적인 용도가 있습니까?
답변
하나의 라이너 대안-파일의 내용을 변수로 설정 :
VAR=`cat file_name`; echo "$VAR"|grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' > file_name
답변
이 질문이 검색 엔진의 상위 결과이므로 다음은 대신 하위 셸을 사용하는 https://serverfault.com/a/547331 을 기반으로 한 한 줄 입니다 sponge
(종종 OS X와 같은 바닐라 설치의 일부가 아님). :
echo "$(grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name)" > file_name
일반적인 경우는 다음과 같습니다.
echo "$(cat file_name)" > file_name
위의 솔루션에는 몇 가지주의 사항이 있습니다.
printf '%s' <string>
대신에를 사용echo <string>
하여 포함 된 파일-n
이 원치 않는 동작을 일으키지 않도록해야합니다 .- 뉴 라인 후행 명령 대체 스트립 ( 이 bash는 같은 포탄의 버그 / 기능입니다 ) 우리는 같은 접미사 문자를 추가해야하므로
x
출력과를 통해 외부에 제거 임시 변수의 매개 변수 확장 과 같은${v%x}
. . - 임시 변수를 사용 하면 현재 쉘 환경
$v
에있는 기존 변수의 값이 스톰 핑$v
되므로 이전 값을 유지하려면 전체 표현식을 괄호로 묶어야합니다. - bash와 같은 쉘의 또 다른 버그 / 기능은 명령 대체
null
가 출력에서 와 같이 인쇄 할 수없는 문자를 제거한다는 것 입니다. 나는 이것을 호출dd if=/dev/zero bs=1 count=1 >> file_name
하고cat file_name | xxd -p
. 그러나echo $(cat file_name) | xxd -p
벗겨집니다. 따라서이 답변은 Lynch가 지적했듯이 이진 파일이나 인쇄 할 수없는 문자를 사용하는 모든 항목에 사용 해서는 안됩니다 .
일반적인 솔루션 (약간 느리고 메모리 집약적이며 여전히 인쇄 할 수없는 문자 제거)은 다음과 같습니다.
(v=$(cat file_name; printf x); printf '%s' ${v%x} > file_name)
https://askubuntu.com/a/752451 에서 테스트 :
printf "hello\nworld\n" > file_uniquely_named.txt && for ((i=0; i<1000; i++)); do (v=$(cat file_uniquely_named.txt; printf x); printf '%s' ${v%x} > file_uniquely_named.txt); done; cat file_uniquely_named.txt; rm file_uniquely_named.txt
다음을 인쇄해야합니다.
hello
world
cat file_uniquely_named.txt > file_uniquely_named.txt
현재 쉘에서 호출하는 반면 :
printf "hello\nworld\n" > file_uniquely_named.txt && for ((i=0; i<1000; i++)); do cat file_uniquely_named.txt > file_uniquely_named.txt; done; cat file_uniquely_named.txt; rm file_uniquely_named.txt
빈 문자열을 인쇄합니다.
대용량 파일 (아마 2GB 또는 4GB 이상)에서는 테스트하지 않았습니다.
나는 Hart Simha 와 kos 에게서이 대답을 빌렸다 .