아직 파일이없는 경우에만 파일 끝에 줄을 추가하는 방법은 무엇입니까?


10

스크립트를 방탄으로 만들지 않는 경우에만 줄을 추가하여 파일을 제자리에서 편집하고 싶습니다.

일반적으로 다음과 같은 작업을 수행합니다.

cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF

ansible ( line+ insertafter=EOF+ regexp)을 통해 할 수도 있지만 또 다른 이야기입니다.

vi / ex에서는 다음과 같은 작업을 수행 할 수 있습니다.

ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc

그러나 동일한 라인을 반복하지 않고 라인이 이미 있는지 (따라서 아무것도하지 않는지) 어떻게 확인합니까?

아니면 Ex 편집기에서 더 쉬운 방법이 있습니까?


아웃소싱 할 수 없습니까? grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...(또는 cat그 문제)?
muru

나는 이것이이 접근법 과 비슷한 것이 될 수 있다고 생각 하지만 반대 (문자열이 없을 때 무언가를하십시오).
kenorb

ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
Alex Kroll

1
참고 exportA는 명령 행의 나머지 쉘 단어, NOT 할당하므로. 따라서 변수 할당과 달리 (사용하지 않는 export) 큰 따옴표가 필요하거나 공백에서 깨집니다 . PATH에 경로를 올바르게 추가하는 방법 도 참조하십시오 .
와일드 카드

1
어제 찾고 있던 실제 링크를 찾았습니다 (위의 링크도 좋지만). 지역 변수 할당에 따옴표가 필요합니까?
와일드 카드

답변:


6

방탄 을 원한다면 위의 복잡한 옵션보다 좀 더 이식성이 좋은 것을 원할 것입니다. POSIX 기능을ex 고수 하고 어리석게 간단하게 만들 것입니다. 줄이 몇 줄 있더라도 줄을 제거하고 파일 끝에 추가 한 다음 저장하고 종료하십시오.

ex -sc 'g/^export PATH=\~\/\.composer\/vendor\/bin:\$PATH$/d
$a
export PATH=~/.composer/vendor/bin:$PATH
.
x' ~/.bashrc

견고성을 높이기 위해 정규 표현식을 고정했지만 실수 로이 정규 표현식과 일치하는 것은 거의 불가능하다고 생각합니다 . (고정 된 수단을 사용 ^하고 $그것이 일치하면되므로 정규식은 일치 전체 라인).

+cmdPOSIX 에는 구문이 필요하지 않으며 여러 -c인수 를 허용하는 일반적인 기능도 아닙니다 .


이 작업을 수행하는 여러 가지 간단한 방법이 있습니다. 예를 들어, 파일 끝에 줄을 추가 한 다음 외부 UNIX 필터를 통해 파일의 마지막 두 줄을 실행하십시오 uniq.

ex -sc '$a
export PATH=~/.composer/vendor/bin:$PATH
.
$-,$!uniq
x' input

이것은 매우 깨끗하고 간단하며 POSIX와 완벽하게 호환됩니다. 외부 텍스트 필터링 및 POSIX 지정 쉘 유틸리티이스케이프 기능을ex 사용 합니다.uniq

결론은,되어 ex있다 설계 현재 위치에서 파일 편집과 훨씬 것을 달성 할 수있는 대부분의 휴대용 방법이 아닌 상호 작용하는 방식이다. 그것은 원래도 선행 vi, 실제로-이름이 vi"시각적 편집기"를, 그리고 비 시각적 에디터가이 위에 지어진 했다 ex .)


훨씬 더 단순하고 한 줄로 줄이려면 printf다음 명령을 사용하십시오 ex.

printf %s\\n '$a' 'export PATH=~/.composer/vendor/bin:$PATH' . '$-,$!uniq' x | ex input


2

가능한 해결책은 다음과 같은 기능을 수행하는 것입니다.

function! AddLine()

    let l:res = 0
    g/export PATH=\~\/.composer\/vendor\/bin:\\\$PATH/let l:res = l:res+1

    if (l:res == 0)
        normal G
        normal oexport PATH=~/.composer/vendor/bin:\$PATH
    endif

endfunction

먼저 l:res라인의 발생 횟수를 계산하는 데 사용할 로컬 변수 를 만듭니다 .

우리는 global명령을 사용합니다 : 줄이 일치 할 때마다 l:res증가합니다.

마지막으로 l:res여전히 0이면 파일에 줄이 표시되지 않기 때문에으로 인해 마지막 줄로 이동 하고 추가 할 줄을 쓰는 G새 줄을 만듭니다 o.

1을 참고 내가의 값을 설정하는 데 사용하는 방법 l:res약간 무거운이며에 @ 알렉스가 제시 한 대체 할 수있는 그의 대답 처럼 뭔가를 :

let l:res = search('export PATH=\~\/.composer\/vendor\/bin:\\\$PATH')

참고 2 함수를보다 유연하게 만들기 위해 인수를 사용할 수 있습니다.

function! AddLine(line)

    let l:line =  escape(a:line, "/~$" )

    let l:res = 0
    exe "g/" . l:line . "/let l:res = l:res+1"

    if (l:res == 0)
        normal G
        exe "normal o" . a:line
    endif

endfunction
  • 검색시 문제를 일으킬 수있는 문자 앞에 문자 escape()를 추가하는 방법 \에 유의하십시오 .
  • 또한 \함수를 호출 할 때 여전히 직접 탈출 해야합니다 ( \자동으로 탈출 할 수는 없었습니다 ).

    call AddLine("export PATH=~/.composer/vendor/bin:\\$PATH")
    

2

시험:

ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"

참고 :append하지 작업 내부의 것 if endif예 모드 - 블록을 (참조 VimDoc을 내가 넣어 그래서) norm A...외부.


1

나는 보통 다음을 사용합니다.

perl -i -p0e '$_.="export PATH=~/bin:\$PATH\n" unless m!~/bin:!' ~/.bashrc

1

많은 사람들의 존재를 단순화하고 피하기 위해 \추가 될 줄은 다음과 같습니다 export PATH=mybin:PATH.

주요 전략 : "비- mybin"텍스트 (모든 파일)를 text + mybin-path-definition으로 대체하십시오 .

 vim  +'s#\v%^((.|\n)(mybin:)@!)*%$#&\rexport PATH=mybin:PATH#e' -cx bashrc

또는 더 교훈적인 들여 쓰기 :

s#                                    substitute
   \v                                  very magical to redude \

   %^                                  file begin
   ((.|\n)(mybin:)@!)*                 multi-line str without "mybin:"
                                         (any char not followed by "mybin")*
   %$                                  end of file
 #                                    by

우리가 일치하는 경우 :

  1. &의 전체 텍스트를 가지고 bashrc
  2. & 포함되어 있지 않다 /mybin:/

그래서:

 #                                    by ...
   &                                   all file
   export PATH=mybin:PATH              and the new path
 #e                                   don't complain if patt not found

-cx                                   save and leave 

업데이트 : 마지막으로 vim 스크립트를 만들 수 있습니다.

$ cat bashrcfix

#!/usr/bin/vim -s
:e ~/fakebashrc
:s#\v%^((.|\n)(mybin:)@!)*%$#&\rexport PATH=mybin:PATH#e
:x

chmod 755를 설치하십시오. 용법:bashrcfix


주의 : \v모드에서 =선택 사항을 의미


1

이 답변의 대부분은 좋은 오래된 쉘 명령은 어떻습니까?

grep composer/vender ~/.bashrc || cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF

이것은 쉽게 Bash 함수 일 수 있습니다.

addBashrcPath() {
  if ! grep "$1" ~/.bashrc >/dev/null 2>&1; then
    printf 'export PATH=%s:$PATH' "$1" >> ~/.bashrc
  fi
}

addBashrcPath "~/.composer/vendor/bin"

편집 : grep의 종료 코드가 중요하며이 경우 역 사용이 필요합니다 ! grep. grep -v이 상황에서 예상대로 종료되지 않습니다. 팁 주셔서 감사합니다 @joeytwiddle.


나는 grep -v당신에게 당신이 원하는 종료 코드를 제공 한다고 생각하지 않습니다 . 그러나 그렇게 ! grep해야합니다.
joeytwiddle

이 경우 -v에는 !.
Sukima

바로 그거죠. 그 답을 수정하기 위해 답을 편집 할 수 있습니다.
joeytwiddle

1
1. 문자를 정규식으로 해석 하지 -F않도록 사용해야합니다 grep. 2. -q로 리디렉션하는 대신 사용하십시오 /dev/null. 질문에 대한이전 의견을 참조하십시오 .
muru

좋은 지적입니다. 휴대 -q성과 -F옵션 이 얼마나 궁금 하십니까? 나는 >/dev/null다른 플랫폼들 사이에서 더 보편적 이라고 생각했다 (Sun vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs…)
Sukima
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.