[bash] Bash 명령에서 텍스트 파일 내부 찾기 및 바꾸기

찾은 내용을 주어진 입력 문자열을 대체 말할 수있는 가장 간단한 방법은 무엇인가 abc말을하고, 다른 문자열로 대체 할 XYZ파일은 /tmp/file.txt?

앱을 작성하고 IronPython을 사용하여 SSH를 통해 명령을 실행하고 있습니다. 그러나 유닉스를 잘 모르고 무엇을 찾아야할지 모르겠습니다.

Bash는 명령 줄 인터페이스가 아니라 매우 강력한 스크립팅 언어가 될 수 있다고 들었습니다. 따라서 이것이 사실이라면 나는 당신이 이와 같은 행동을 수행 할 수 있다고 가정합니다.

bash로 할 수 있습니까? 목표를 달성하는 가장 간단한 (한 줄) 스크립트는 무엇입니까?



답변

가장 쉬운 방법은 sed (또는 perl)를 사용하는 것입니다.

sed -i -e 's/abc/XYZ/g' /tmp/file.txt

-i옵션 으로 인해 내부 편집을 수행하기 위해 sed를 호출합니다 . 이것은 bash에서 호출 할 수 있습니다.

정말로 bash 만 사용하고 싶다면 다음과 같이 할 수 있습니다.

while read a; do
    echo ${a//abc/XYZ}
done < /tmp/file.txt > /tmp/file.txt.t
mv /tmp/file.txt{.t,}

이것은 각 행을 반복하여 대체를 수행하고 임시 파일에 기록합니다 (입력을 방해하지 않으려 고 함). 마지막 이동은 임시로 원래 이름으로 이동합니다.


답변

파일 조작은 일반적으로 Bash가 아니라 Bash가 호출 한 프로그램에 의해 수행됩니다. 예 :

perl -pi -e 's/abc/XYZ/g' /tmp/file.txt

-i플래그는 내부 교체를 지시합니다.

man perlrun원본 파일을 백업하는 방법을 포함하여 자세한 내용을 참조하십시오 .


답변

이걸 우연히 발견했을 때 놀랐습니다 …

패키지 replace와 함께 제공 되는 명령이 "mysql-server"있으므로 설치 한 경우 시도해보십시오.

# replace string abc to XYZ in files
replace "abc" "XYZ" -- file.txt file2.txt file3.txt

# or pipe an echo to replace
echo "abcdef" |replace "abc" "XYZ"

이에 man replace대한 자세한 내용 을 참조하십시오 .


답변

이것은 오래된 게시물이지만 @ centurian과 같이 변수를 사용하려는 사람은 작은 따옴표가 아무것도 확장되지 않는다는 것을 의미한다고 말했습니다.

변수를 가져 오는 간단한 방법은 문자열 연결을 수행하는 것입니다. 이는 bash에서 병렬로 수행되므로 다음과 같이 작동합니다.

sed -i -e "s/$var1/$var2/g" /tmp/file.txt


답변

다른 쉘과 마찬가지로 Bash는 다른 명령을 조정하는 도구 일뿐입니다. 일반적으로 표준 UNIX 명령을 사용하려고 시도하지만 Bash를 사용하여 컴파일 된 프로그램, 다른 쉘 스크립트, Python 및 Perl 스크립트 등을 포함하여 무엇이든 호출 할 수 있습니다.

이 경우 몇 가지 방법이 있습니다.

파일을 읽고 다른 파일에 쓰려면 검색 / 바꾸기를 수행하면서 sed를 사용하십시오.

sed 's/abc/XYZ/g' <infile >outfile

편집기에서 파일을 열고 편집 한 후 저장하는 것처럼 파일을 제자리에서 편집하려면 라인 편집기 ‘ex’에 지시 사항을 제공하십시오.

echo "%s/abc/XYZ/g
w
q
" | ex file

Ex는 전체 화면 모드가없는 vi와 같습니다. vi의 ‘:’프롬프트에서와 동일한 명령을 제공 할 수 있습니다.


답변

나는이 스레드를 다른 사람들과 함께 발견했으며 가장 완벽한 답변을 포함하고 있음을 동의하므로 내 것을 추가하고 있습니다.

  1. sed그리고 ed손으로 너무 유용합니다. @Johnny 에서이 코드를보십시오 :

    sed -i -e 's/abc/XYZ/g' /tmp/file.txt
  2. 내 제한이 쉘 스크립트에서 사용되는 경우, “abc”또는 “XYZ”대신 변수를 사용할 수 없습니다. BashFAQ은 내가 적어도 이해하는 것을 동의 것으로 보인다. 그래서 나는 사용할 수 없습니다 :

    x='abc'
    y='XYZ'
    sed -i -e 's/$x/$y/g' /tmp/file.txt
    #or,
    sed -i -e "s/$x/$y/g" /tmp/file.txt

    그러나 우리는 무엇을 할 수 있습니까? @Johnny는 사용 while read...하지만 불행히도 그 이야기의 끝은 아닙니다. 다음은 나와 잘 작동했습니다.

    #edit user's virtual domain
    result=
    #if nullglob is set then, unset it temporarily
    is_nullglob=$( shopt -s | egrep -i '*nullglob' )
    if [[ is_nullglob ]]; then
       shopt -u nullglob
    fi
    while IFS= read -r line; do
       line="${line//'<servername>'/$server}"
       line="${line//'<serveralias>'/$alias}"
       line="${line//'<user>'/$user}"
       line="${line//'<group>'/$group}"
       result="$result""$line"'\n'
    done < $tmp
    echo -e $result > $tmp
    #if nullglob was set then, re-enable it
    if [[ is_nullglob ]]; then
       shopt -s nullglob
    fi
    #move user's virtual domain to Apache 2 domain directory
    ......
  3. 다음과 같이 nullglob설정되어 있는지 확인할 수 있듯이 *as를 포함하는 문자열이 있으면 이상하게 동작합니다 .

    <VirtualHost *:80>
     ServerName www.example.com

    이것은

    <VirtualHost ServerName www.example.com

    끝 꺾쇠 괄호가 없으며 Apache2도로드 할 수 없습니다.

  4. 이러한 종류의 구문 분석은 한 번의 검색 및 바꾸기보다 속도가 느려 야하지만 이미 살펴본 것처럼 한 번의 구문 분석주기에서 작동하는 4 가지 다른 검색 패턴에 대한 4 개의 변수가 있습니다.

주어진 문제에 대한 가정으로 생각할 수있는 가장 적합한 솔루션입니다.


답변

당신은 사용할 수 있습니다 sed:

sed -i 's/abc/XYZ/gi' /tmp/file.txt

사용 -i이 발견하지 않도록 텍스트 경우 “경우 무시”에 대한은 abcABC이나 AbC

당신은 사용 find하고 sed당신이 당신의 이름을 모르는 경우 :

find ./ -type f -exec sed -i 's/abc/XYZ/gi' {} \;

모든 파이썬 파일에서 찾기 및 바꾸기 :

find ./ -iname "*.py" -type f -exec sed -i 's/abc/XYZ/gi' {} \;