텍스트 파일에 일부 문자열 데이터를 추가하는 Unix 명령이 있습니까?
다음과 같은 것 :
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
텍스트 파일에 일부 문자열 데이터를 추가하는 Unix 명령이 있습니까?
다음과 같은 것 :
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
답변:
sed -i.old '1s;^;to be prepended;' inFile
-i
변경 사항을 기록하고 확장이 제공되면 백업을 수행합니다. (이 경우 .old
)1s;^;to be prepended;
;
명령 구분 기호로 사용하여 첫 번째 줄의 시작 부분을 지정된 대체 문자열로 대체합니다 .\n
앞에 추가 한 후에 삽입 할 수 있습니다 . 그들의 필요에 따라. 깔끔한 솔루션.
inFile
경로에 디렉토리를 포함 할 수 있습니까 ?
\n
. 먼저 댓글을 읽어야 했어요. 제길.
'1s;^;my-prepended-line\;\n;'
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
git config --get-regex $arg | sed -r 's/\t{3}/\\n/g';
가 변환으로이 망쳐 놨까지 \t
하고 \n
.
echo "to be prepended"$'\n'"$(cat text.txt)"
아무도 이것을 언급하지 않았다는 것에 놀랐습니다.
cat <(echo "before") text.txt > newfile.txt
이것은 받아 들여진 대답보다 더 자연 스럽습니다 (무언가를 인쇄하고이를 대체 명령에 연결하는 것은 사 전적으로 반 직관적입니다).
... 위에서 라이언이 말한 것을 납치 sponge
하면 임시 파일이 필요하지 않습니다.
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
편집 : Bourne Shell에서 작동하지 않는 것 같습니다. /bin/sh
here-string-사용하여 <<<
다음을 수행 할 수 있습니다.
<<< "to be prepended" < text.txt | sponge text.txt
<<(echo "to be prepended") < text.txt
및 <<< "to be prepended" < text.txt
구성은 bash에서 작동하지 않습니다. zsh가 필요합니다.
이것은 한 가지 가능성입니다.
(echo "to be prepended"; cat text.txt) > newfile.txt
중간 파일을 쉽게 다룰 수 없을 것입니다.
대안 (셸 이스케이프로 인해 번거로울 수 있음) :
sed -i '0,/^/s//to be prepended/' text.txt
cat <(echo "to be prepended") text.txt > newfile.txt
. 생각해 보니 내 것이 관련이 있는지 확실하지 않으므로 별도의 답변을 게시했습니다.
이것은 출력을 형성하는 데 작동합니다. -는 에코에서 파이프를 통해 제공되는 표준 입력을 의미합니다.
echo -e "to be prepended \n another line" | cat - text.txt
파일을 다시 쓰려면 입력 파일로 다시 파이프 할 수 없으므로 임시 파일이 필요합니다.
echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
text.txt
요청한대로 파일 앞에 텍스트를 추가하지는 않지만 stdout에 표시합니다. OP에서 작동하는 경우 출력은 다른 파일로 유입 될 수 있습니다
노트 :
그렇게하면 예상치 못한 부작용이 발생할 수 있습니다. 특히 심볼릭 링크를 일반 파일로 대체하고 파일에 대한 다른 권한을 갖게되며 파일 생성 (생년월일) 날짜가 변경 될 수 있습니다.
sed -i
, Prince John Wesley의 답변 에서와 같이 최소한 원래 권한을 복원하려고 시도하지만 다른 제한 사항도 적용됩니다.
다음 은 임시 파일을 사용 하는 간단한 대안입니다 ( shime의 솔루션 이 수행 하는 방식으로 전체 입력 파일을 메모리로 읽는 것을 방지합니다 ).
{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
사용하여 그룹 명령은 ( { ...; ...; }
)를 사용하는 것보다 약간 더 효율적입니다 서브 쉘을 ( (...; ...)
같이) 0xC0000022L의 솔루션 .
장점은 다음과 같습니다.
그것은 새로운 텍스트를 직접 첫 번째 줄 앞에 추가할지 여부를 제어하기 쉽게하거나 삽입 할 것인지 등의 새로운 라인 (들) (단순히 APPEND \n
받는 printf
인수).
sed
솔루션 과 달리 입력 파일이 비어 있으면 ( 0
바이트) 작동합니다.
sed
솔루션은 의도는 하나 개 이상의 앞에 추가하는 경우 간단하게 할 수있는 전체 라인을 (입력 파일이 비어 있지 가정) 기존 내용 :
sed
의 i
함수는 전체 행을 삽입합니다.
와 GNU sed
:
# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile
macOS / BSD에서도 작동하는 휴대용 변형 sed
:
# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile
뒤에 오는 리터럴 개행 문자 \
가 필요합니다.
오래된 ed
POSIX 유틸리티 사용 :
노트 :
ed
항상 입력 파일 전체 를 메모리로 먼저 읽습니다 .첫 번째 줄에 직접 추가 하려면 (와 마찬가지로 sed
입력 파일이 완전히 비어 있으면 ( 0
바이트) 작동하지 않음 ) :
ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
-s
ed
의 상태 메시지를 억제했습니다 .ed
여러 줄의 here-document ( <<EOF\n...\nEOF
), 즉 stdin을 통해 제공되는 방법에 유의 하십시오 . 기본적으로 문자열 확장 은 이러한 문서에서 수행됩니다 (쉘 변수는 보간됩니다). 이를 억제하려면 여는 구분 기호를 인용 하십시오 (예 :) <<'EOF'
.1
첫 번째 줄을 현재 줄로 만듭니다.s
는 다음과 같이 현재 줄에서 정규식 기반 문자열 대체를 수행합니다 sed
. 대체 텍스트에 리터럴 개행 문자를 포함 할 수 있지만\
이스케이프 처리 .w
(테스트하기 위해, 대체 입력 파일에 결과 등을 기록 w
으로 ,p
만에 인쇄 입력 파일을 수정하지 않고, 그 결과를).하나 이상의 전체 행 을 앞에 추가 하려면 다음을 수행하십시오 .
와 같이, sed
상기 i
기능은 변함없이 텍스트에 후행 개행을 삽입 할 추가한다.
ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
0 i
차종 0
합니다 (파일의 시작) 모드 삽입 현재 라인이 시작 ( i
); 줄 번호는 그렇지 않으면 1
기반입니다..
이며 자체 줄 에서 끝납니다 .아마도 내장 된 것은 없지만 다음과 같이 꽤 쉽게 작성할 수 있습니다.
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
적어도 그런 건 ...
$$
그러나 프로덕션 코드에는 사용 이 충분하지 않습니다 (구글 심볼릭 링크 공격). 하지만 정적 파일 이름보다 확실히 낫습니다.
mktemp
경우에 따라 앞에 추가 된 텍스트는 stdin에서만 사용할 수 있습니다. 그러면이 조합이 작동합니다.
echo "to be prepended" | cat - text.txt | tee text.txt
tee
출력 을 생략하려면 > /dev/null
.
tee
방해하지 않는 보증이 있습니까? 나는 그렇지 않다고 생각한다. 이것은이 솔루션을 파일의 건강에 위험하게 만들 것이다. text.txt
cat
lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null
. 경우 lenA
1,000,000 (1MB의 파일)과 lenB
(10KB 텍스트 앞에 추가) 10000, 다음 "a.txt이"가 "B"문자 20KB로 덮어 파일. 이것은 완전히 망가졌습니다. 이제 1Mb a.txt와 1Mb 텍스트를 사용하여 앞에 추가하고 tee
7Gb + 파일을 생성하는 루프에 들어가면 명령을 중지해야했습니다. 따라서 큰 크기의 경우 결과를 예측할 수 없음이 분명합니다. 작은 크기에서 작동할지 여부에 대한 정보가 없습니다.
해결책:
printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt
확장이 없기 때문에 모든 종류의 입력에서 안전합니다. 예를 들어, 앞에 추가하려면 다음 !@#$%^&*()ugly text\n\t\n
과 같이 작동합니다.
printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt
고려할 마지막 부분은 명령 대체 동안 파일 끝에서 공백을 제거하는 것입니다 "$(cat file.txt)"
. 이에 대한 모든 해결 방법은 비교적 복잡합니다. file.txt 끝에서 줄 바꿈을 유지 하려면 https://stackoverflow.com/a/22607352/1091436을 참조하십시오.
file.txt
인수 목록에 들어갈 수있는 것보다 큰 경우에 발생합니다 printf
.
사용하는 또 다른 방법 sed
:
sed -i.old '1 {i to be prepended
}' inFile
추가 할 줄이 여러 줄인 경우 :
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile
sed -i '1ito be prepended' inFile
됩니까? 아니면 GNU sed에서만 허용됩니까?
sed
에서 i
명령 뒤에 백 슬래시와 줄 바꿈이오고 마지막을 제외한 각 입력 줄도 백 슬래시로 끝납니다. GNU sed
는 당신이 묻는 줄에 속기를 허용하지만 sed
그렇게하는 것은 GNU뿐입니다 . '
다음을 통해 테스트 파일로 시작하는 경우 Bash (Ubuntu)에서 테스트했습니다.
echo "Original Line" > test_file.txt
실행할 수 있습니다.
echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt
또는 bash의 버전이 $ ()에 비해 너무 오래된 경우 백틱을 사용할 수 있습니다.
echo "`echo "New Line"; cat test_file.txt`" > test_file.txt
"test_file.txt"의 다음 내용을 수신합니다.
New Line
Original Line
중개 파일이없고 bash / echo 만 있습니다.
또 다른 매우 간단한 해결책은 다음과 같습니다.
$ echo -e "string\n" $(cat file)
cat
따옴표로 매개 변수 확장하는 것은위한 꽤 좋은 이유입니다 downvote . 이 코드는 파일의 내용을 단어로 분할하고 각 단어를 별도의 인수로에 전달합니다 echo
. 원래 인수 경계를 잃고 개행 / 탭 / 등을 잃고 원래 텍스트 \t
와 같은 문자열 \n
은 그대로 유지되는 대신 탭과 개행으로 대체됩니다.
함수를 정의한 다음 필요한 곳에 가져 와서 사용하는 것이 좋습니다.
prepend_to_file() {
file=$1
text=$2
if ! [[ -f $file ]] then
touch $file
fi
echo "$text" | cat - $file > $file.new
mv -f $file.new $file
}
그런 다음 다음과 같이 사용하십시오.
prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"
그러면 파일 내용은 다음과 같습니다.
This is second
This is first
변경 로그 업데이트 프로그램을 구현하는 데이 접근 방식을 사용하려고합니다.