Solaris에서 "sed -i"명령에 대한 대안이 있습니까?


11

내 프로젝트에서 파일의 기존 텍스트를 다음과 같은 foo다른 텍스트로 바꾸어야합니다 fooofoo.

abc.txt
name
foo
foo1

그래서 나는 시도했다 :

sed -i "s/foo/fooofoo/g" abc.txt

그러나이 오류가 발생합니다.

sed : 불법 옵션- i

매뉴얼에서 다음을 사용해야한다는 것을 알았습니다.

sed -i\ "s/foo/fooofoo/g" abc.txt

그러나 이것은 작동하지 않습니다.

나는에서 대안을 발견 perl하고 awk도를하지만 솔라리스에서 솔루션이 sed많이 주시면 감사하겠습니다.

이 버전의 bash를 사용하고 있습니다.

GNU bash, 버전 3.2.57 (1)-릴리스 (sparc-sun-solaris2.10)


Solaris 11 이상에서 간단히 /usr/gnu/bin/sed-i 지원을 받으려면 사용하십시오 .
alanc

답변:


15

사용하십시오 ed. 대부분의 플랫폼에서 사용 가능하며 파일을 제자리에서 편집 할 수 있습니다.
이후 sed에 기반 ed패턴을 교체하는 구문과 유사하다 :

ed -s infile <<\IN
,s/old/new/g
w
q
IN

ed대신에 ex궁금한가? (둘 다 POSIX를 준수하고 사양에 연결되어 있음을 알고 있습니다.;))
Wildcard

1
@ Wildcard- 반대를 물어볼 수있는 이유는 ex무엇입니까? 귀하의 질문에 대답하기 위해 : 나는 결코 사용하지 않기 때문에 나는 ex 그것에 익숙하지 않습니다. btw, 나는 ed존재하지만 ex(반대가 아닌) 설치가있는 곳 을 보았습니다 ... 가장 주목할만한 내 노트북 ​​:)
don_crissti

좋은 대답입니다. :) 내 대답 : Vim을 항상 사용하기 때문에 ex명령에 매우 익숙 합니다. vi콜론으로 시작하는 입력 할 수있는 모든 명령은 ex명령입니다. 물론 Vim 고유의 확장 기능이 몇 가지 있지만 핵심 명령 세트만으로도 강력하고 유연하며 스크립트 편집에 충분합니다.
와일드 카드

나의 만자로 시스템은 ex아직 없습니다 ed.
중순

8

GNU sed를 설치할 수 없으면 다음을 사용하십시오.

sed "s/foo/fooofoo/g" abc.txt >abc.tmp && mv abc.tmp abc.txt

이것은 리디렉션 을 사용 하여 sed의 출력을 임시 파일로 보냅니다. sed가 성공적으로 완료되면 abc.txt임시 파일로 덮어 씁니다 .

GNU sed의 소스 코드에서 알 수 있듯이 , 이것이 정확히하는 일 sed -i입니다. 따라서 이것은 거의 효율적 sed -i입니다.

abc.tmp이미 존재할 가능성이있는 경우 mktemp임시 유틸리티의 고유 이름을 생성 하기 위해 또는 유사한 유틸리티를 사용할 수 있습니다 .


도움에 감사드립니다. 그러나 임시 파일을 만들지 않고 기존 파일을 업데이트 할 수있는 옵션이 solaris에 있습니까?
tpsaitwal

10
그것을 부수기 싫어하지만 sed조차도 임시 파일을 만듭니다. git.savannah.gnu.org/cgit/sed.git/tree/sed/sed.c#n84
Jeff Schaller

1
하드 링크에 신경 쓰지 않으면 할 수 있습니다-내 예를 참조하십시오. 여전히 임시 파일이 있지만 숨겨져 있습니다 (이름이 없음). 임시 파일이 없으면 ed전체 파일을 메모리로 읽어 들이기 때문에 를 사용해야 합니다.
Toby Speight

3

와 동등한 것을 원한다면 sed -i.bak매우 간단합니다.

GNU sed에 대한이 스크립트를 고려하십시오.

#!/bin/sh

# Create an input file to demonstrate
trap 'rm -r "$dir"' EXIT
dir=$(mktemp -d)
grep -v '[[:upper:][:punct:]]' /usr/share/dict/words | head >"$dir/foo"

# sed program - removes 'aardvark' and 'aardvarks'
script='/aard/d'

##########
# What we want to do
sed -i.bak -e "$script" "$dir"
##########

# Prove that it worked
ls "$dir"
cat "$dir/foo"

표시된 줄을 간단히 바꿀 수 있습니다.

cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"

기존 파일을 백업으로 이동하고 새 파일을 씁니다.

우리가

sed -i -e "$script" "$dir"  # no backup

약간 더 복잡합니다. sed의 출력을 대체하도록 지시하기 전에 표준 입력으로 읽을 파일을 열고 링크를 해제 할 수 있습니다.

( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )

서브 쉘에서이 작업을 수행 한 후에도 원래 stdin을 계속 사용할 수 있습니다. 서브 쉘없이 입력을 전환하고 다시 전환하는 것이 가능하지만이 방법은 나에게 더 명확 해 보입니다.

foo파일을 만들지 않고 먼저 복사 해야합니다. 파일이 둘 이상의 이름으로 알려져 있고 (예 : 하드 링크가있는 경우) 링크를 끊지 않도록하려면 중요합니다. .


3

먼저, i\참조 하는 명령 은 편집 된 텍스트를 파일에 다시 저장하는 것이 아니라 텍스트삽입하는 것 입니다. 더 없다 POSIX가 지정한 방식으로 사용하는 sed그것을 위해가.

당신이 일은 사용이다 ex, 있다 POSIX에 의해 지정된 :

printf '%s\n' '%s/find/replace/g' 'x' | ex file.txt

x명령입니다 "저장하고 종료합니다." 사용할 수도 wq있지만 x더 짧습니다.

%대체 명령 수단의 시작 기호, "버퍼의 모든 라인에이 명령을 적용합니다." 사용할 1,$s/find/replace/g수도 있습니다.


사이에 하나 개의 큰 차이 ex와는 sedsedA는 스트림 편집기. 한 줄씩 순차적으로 만 작동합니다. ex그보다 훨씬 유연하며 실제로 대화 형 텍스트 파일 편집을 직접 수행 할 수 있습니다 ex. 바로 전임자 vi입니다.


1

보이는 임시 파일 사용 sed표시 안함 :

별도의 보이는 "임시 파일"을 작성하지 않아도됩니다.

exec 3<abc.txt
rm abc.txt
sed 's/foo/fooofoo/' <&3 >abc.txt
exec 3<&-

설명

유닉스 계열 시스템은이 때까지 실제로 디스크에서 파일의 내용을 제거하지 마십시오 모두 파일 시스템에 연결되지 않은, 그리고 어떤 과정에서 열 수 없습니다. 따라서 exec 3<파일 디스크립터 3, rm파일 (파일 시스템에서 링크 해제 된 파일)을 읽기 위해 셸에서 파일을 연 다음 sed입력으로 사용 된 파일 디스크립터 3 을 호출 할 수 있습니다.

이것은 이것과 매우 다릅니다.

# Does not work.
sed 's/foo/fooofoo/' <abc.txt >abc.txt

차이점은 하나의 명령으로 수행 할 때 셸은 읽기와 파일 자르기 옵션으로 쓰기 위해 동일한 파일을 여는 것입니다. 파일이 여전히 동일하므로 내용이 손실됩니다. 그러나 읽기 위해 rm파일을 연 다음 쓰기 위해 동일한 경로 이름을 열면 실제로 동일한 경로 이름으로 새 파일을 만드는 것입니다 (그러나 원본이 여전히 열려 있기 때문에 새로운 inode 및 디스크 위치에 있음). 내용은 여전히 ​​사용할 수 있습니다.

그런 다음, 이전에 열었던 파일 디스크립터 ( exec 3<&-특수 구문이하는 것)를 닫을 수 있습니다. 이렇게하면 운영 체제가 디스크 공간을 삭제 (사용되지 않은 것으로 표시) 할 수 있습니다.

경고

이 솔루션에 대해 명심해야 할 것이 몇 가지 있습니다.

  1. 컨텐츠를 통해 하나의 "go"만 얻을 수 있습니다 . 쉘이 파일 디스크립터에서 "검색"할 수있는 휴대용 방법은 없습니다. 따라서 프로그램이 일부 컨텐츠를 읽으면 다른 프로그램은 나머지 파일 만 볼 수 있습니다. 그리고 sed전체 파일을 읽습니다.

  2. 쉘 / 스크립트 / sed가 완료되기 전에 죽으면 원본 파일이 손실 될 가능성이 적습니다.


분명히, @TobySpeight는 이미 그의 대답 끝에이 솔루션의 예를 게시했지만 더 심층적 인 정교함을 사용할 수 있다고 생각했습니다.
mtraceur

downvoter에게 : downvote를 남겨두면 자신에 대해 기분이 좋아 진다고 확신하지만,이 답변에 어떤 문제가 있는지, 어떻게 개선 될 수 있는지 등에 대한 피드백을 제공함으로써 더 많은 기여를한다면 감사하겠습니다. .
mtraceur

아마도 당신은 perl -i
c4f4t0r을

@ c4f4t0r : 늦게 답변 죄송합니다 : 예, perl -i또 다른 좋은 옵션입니다. 문제는 특히 솔라리스와 호환 솔루션 '요구 sed와 솔루션 대비를, perl그리고 awk그들이 찾는 이미 언급 한. 또한, 내 대답은 주로 내가 알고 있고 다른 대답에서 누락 된 것으로 생각되는 것을 추가하려고했습니다.
mtraceur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.