명령에서 파일을 사용하고 출력을 자르지 않고 동일한 파일로 리디렉션하려면 어떻게해야합니까?
기본적으로 파일에서 입력 텍스트로 가져 와서 해당 파일에서 한 줄을 제거하고 출력을 동일한 파일로 다시 보내고 싶습니다. 이 선을 따라 가면 더 명확 해집니다.
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
https://askubuntu.com/a/752451 에서 테스트 :
printf "hello\nworld\n" > file_uniquely_named.txt && for ((i=0; i<1000; i++)); do echo "$(cat file_uniquely_named.txt)" > 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 에게서이 대답을 빌렸다 .
도 있습니다 ed
(대안으로 sed -i
) :
# cf. http://wiki.bash-hackers.org/howto/edit-ed
printf '%s\n' H 'g/seg[0-9]\{1,\}\.[0-9]\{1\}/d' wq | ed -s file_name
process-substitution 을 사용하여이를 수행 할 수 있습니다 .
bash가 모든 파이프를 비동기 적으로 열어서 sleep
YMMV 를 사용하여 이를 해결해야하기 때문에 약간의 해킹 입니다.
귀하의 예에서 :
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > >(sleep 1 && cat > file_name)
>(sleep 1 && cat > file_name)
grep에서 출력을받는 임시 파일을 만듭니다.sleep 1
입력 파일을 구문 분석하는 grep 시간을 제공하기 위해 1 초 동안 지연- 마지막으로
cat > file_name
출력을 씁니다.
POSIX Awk와 함께 slurp를 사용할 수 있습니다.
!/seg[0-9]\{1,\}\.[0-9]\{1\}/ {
q = q ? q RS $0 : $0
}
END {
print q > ARGV[1]
}
I usually use the tee program to do this:
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | tee file_name
It creates and removes a tempfile by itself.
Try this
echo -e "AAA\nBBB\nCCC" > testfile
cat testfile
AAA
BBB
CCC
echo "$(grep -v 'AAA' testfile)" > testfile
cat testfile
BBB
CCC
The following will accomplish the same thing that sponge
does, without requiring moreutils
:
shuf --output=file --random-source=/dev/zero
The --random-source=/dev/zero
part tricks shuf
into doing its thing without doing any shuffling at all, so it will buffer your input without altering it.
However, it is true that using a temporary file is best, for performance reasons. So, here is a function that I have written that will do that for you in a generalized way:
# Pipes a file into a command, and pipes the output of that command
# back into the same file, ensuring that the file is not truncated.
# Parameters:
# $1: the file.
# $2: the command. (With $3... being its arguments.)
# See https://stackoverflow.com/a/55655338/773113
function siphon
{
local tmp=$(mktemp)
local file="$1"
shift
$* < "$file" > "$tmp"
mv "$tmp" "$file"
}
'development' 카테고리의 다른 글
사용자 정의 std :: set 비교기 사용 (0) | 2020.09.23 |
---|---|
GridView가 양식 태그 내에 있더라도 runat =“server”인 양식 태그 내에 GridView를 배치해야합니다. (0) | 2020.09.23 |
SVN 사용자 이름 변경 (0) | 2020.09.23 |
Java의 평가 순서에 대한 규칙은 무엇입니까? (0) | 2020.09.23 |
64 비트 또는 32 비트 노드 실행 파일이 설치되어 있는지 확인하는 방법은 무엇입니까? (0) | 2020.09.23 |