Bash의 문자열에서 마지막 n 문자를 제거하는 방법은 무엇입니까?


202

varBash 스크립트에 문자열을 보유 하는 변수 가 있습니다.

echo $var
"some string.rtf"

나는이 문자열의 마지막 4 개 문자를 제거하고 새 변수에 결과를 할당 할 var2그래서,

echo $var2
"some string"

어떻게해야합니까?


답변:


15

먼저, 당신이 원하는 것에 대해 명시해야합니다. 문자열이 끝나고을 .rtf제거하려는 경우을 .rtf사용할 수 있습니다 var2=${var%.rtf}. 접미사가 무엇인지 모르지만 마지막으로 시작하는 모든 것을 제거 .하려면을 사용할 수 있습니다 var2=${var%.*}. 모든 것을 처음에만 유지 .하려면 사용할 수 있습니다 var2=${var%%.*}. 마지막 두 옵션은 기간이 하나만 있으면 동일한 결과를 갖지만 둘 이상이있을 경우 원하는 것을 결정해야합니다.

항상 정확한 수의 문자를 제거하려면 몇 가지 옵션이 있습니다.

bash를 구체적으로 지정 했으므로 bash 내장으로 시작할 것입니다. 가장 오래 일한 것은 위에서 사용한 것과 동일한 접미사 제거 구문 var2=${var%????}입니다. 네 문자를 제거하려면을 사용하십시오 . 제거 된 문자 당 하나의 물음표가 필요하므로 더 큰 부분 문자열 길이에서는 다루기가 어려워집니다.

부분 문자열 추출은 약간 더 최신입니다 : var2=${var::${#var}-4}. 여기 4에 다른 수의 문자를 제거하기 위해 대신 숫자를 입력 할 수 있습니다 . ( ${#var}문자열의 길이로 대체되므로 실제로 첫 번째 (길이-4) 문자를 유지하도록 요청합니다.)

최신 버전의 bash (특히 4 이상, MacOS와 함께 제공되는 버전은 작동하지 않음)를 사용하면 단순화 할 수 있습니다 var2=${var::-4}.

실제로 bash를 사용하지 않고 다른 POSIX 유형 쉘을 사용하는 경우 접미사 제거는 평범한 오래된 대시 (나머지가없는 곳)에서도 여전히 작동합니다. zsh에서는 모두 작동하지만 0콜론 사이에 공백 을 넣어야합니다 . var2=${var:0:-4}etc. ksh에서는 0이 필요하며 명시적인 길이 -4 표현식도 사용해야합니다 var2=${var:0:${#var}-4}.

물론 유틸리티 프로그램의 도움으로 명령 대체를 사용할 수 있습니다. 효과가 충분하지만 var2=$(cut -c -4 <<<"$var")아마도 가장 짧은 옵션 일 것입니다.


240

당신은 이렇게 할 수 있습니다 :

#!/bin/bash

v="some string.rtf"

v2=${v::-4}

echo "$v --> $v2"

9
bash 4+ 생각합니다.
Etan Reisner

69
그것은이다 bash4+하지만, 이전 버전에서 당신은 약간 더 사용할 수 있습니다 ${v::${#v}-4}.
chepner

8
나를 위해 일하지 않았다 배쉬 ''나쁜 '교체 교체 말한다
이반 Marjanovic

15
어떤 이유로 zsh ${v::-4}croaks에서 "zsh : 닫기 괄호 예상". 그러나 @fredtantini의 답변은 아래에서 ${v:0:-4}잘 작동합니다.
Pierre D

6
오류 : -2 : 부분 문자열 표현식 <0
Edward

172

문자열 끝에서 네 문자를 제거하려면을 사용하십시오 ${var%????}.

최종 .사용 후 모든 것을 제거 합니다 ${var%.*}.


12
순수 쉘 답변이며 라이센스 문제로 인해 BASH 4.x 구현을 거부 한 많은 시스템에서 발견되는 BASH 3.x에서 작동합니다.
David W.

1
더 짧은 줄을 얻는 것에 대해 강력하기 때문에 멋지다. 그러면 인덱스 오프셋 변형이 실패합니다.
Raphael

bash 3.2.25에서 작동-최고의 답변-내가 찾던 것
capser

훌륭한 답변입니다. 줄 앞의 제거는 어떻습니까?
user2023370

3
@ user2023370 설명서를 참조하면 해당 매개 변수로 대체 된 것이 밝혀 져야 ${var#????}합니다.
tripleee

48

나를 위해 일한 것은 다음과 같습니다.

echo "hello world" | rev | cut -c5- | rev
# hello w

그러나 파일에서 줄을 자르는 데 사용했기 때문에 어색해졌습니다. 실제 용도는 다음과 같습니다.

cat somefile | rev | cut -c5- | rev

cut일부 시작 위치에서 트리밍하는 것만 가능합니다. 가변 길이 행이 필요한 경우 좋지 않습니다. 따라서이 솔루션 rev은 문자열을 뒤집고 ( ) 이제 끝 위치와 관련이 있으며 cut언급 한대로 사용 하고 rev원래 순서로 되돌립니다 (다시 ).


이것은 정확하지 않으며 요청되는 내용에 대한 답변이 아닙니다. rev문자열이 아닌 행을 반대로합니다. echo $SOME_VAR | rev | ...아마 사람이 어떻게 기대하는지 행동하지 않을 것입니다.
모하마드 나시 리파

2
때문에의 @Mohammad , 인용 고장있다 한 줄.
tripleee

38

사용 변수 확장 / 하위 문자열 교체 :

$ {var / % Pattern / Replacement}

var의 접미사가 Pattern과 일치하면 Replace를 Pattern으로 대체하십시오.

그래서 당신은 할 수 있습니다 :

~$ echo ${var/%????/}
some string

또는

항상 같은 4 글자가 있다면

~$ echo ${var/.rtf/}
some string

항상 끝나는 경우 .xyz:

~$ echo ${var%.*}
some string

문자열 길이를 사용할 수도 있습니다.

~$ len=${#var}
~$ echo ${var::len-4}
some string

또는 단순히 echo ${var::-4}


len=${#var}; echo ${var::len-4}echo ${var:0:-4}:-) 편집 으로 단축 될 수 있습니다 : 또는 @ iyonizer가 지적했듯이 그냥 echo ${var::-4}...
anishsane

26

sed를 사용할 수 있습니다.

sed 's/.\{4\}$//' <<< "$var"

예:

$ var="some string.rtf"
$ var1=$(sed 's/.\{4\}$//' <<< "$var")
$ echo $var1
some string

1
결과를 var2어떻게 할당 합니까?
becko December

이 같은 한 줄에 작동하기 때문에 이것은 좋은 ... | sed 's /. \ {4 \} $ //'. 변수를 사용하지 않고 사용할 수 있음
Sam

3

나는 다음을 시도했고 그것은 나를 위해 일했다 :

#! /bin/bash

var="hello.c"
length=${#var}
endindex=$(expr $length - 4)
echo ${var:0:$endindex}

산출: hel


1

아래 예제가 도움이되기를 바랍니다.

echo ${name:0:$((${#name}-10))} -> ${name:start:len}

  • 위의 명령에서 name은 변수입니다.
  • start 문자열 시작점입니다
  • len 제거해야하는 문자열의 길이입니다.

예:

    read -p "Enter:" name
    echo ${name:0:$((${#name}-10))}

산출:

    Enter:Siddharth Murugan
    Siddhar

참고 : Bash 4.2는 음의 하위 문자열에 대한 지원을 추가했습니다.


이것은 Etan Reisner의 답변에서와 같이 Bourne 호환 간단한 패턴 대체보다 훨씬 더 장황합니다.
tripleee

0

이것은 문자열의 크기를 계산하여 나를 위해 일했습니다.
반환해야 할 값을 에코 한 다음 아래와 같이 저장해야합니다.

removechars(){
        var="some string.rtf"
        size=${#var}
        echo ${var:0:size-4}  
    }
    removechars
    var2=$?

어떤 문자열


0

이 경우 제거하려는 파일에 동일한 접미사가 있다고 가정하면 basename을 사용할 수 있습니다.

예:

basename -s .rtf "some string.rtf"

이것은 "일부 문자열"을 반환합니다

접미사를 모르고 마지막 점을 포함한 모든 점을 제거하려면 다음을 수행하십시오.

f=file.whateverthisis
basename "${f%.*}"

"파일"을 출력합니다

%는 절단을 의미합니다. 당신이 자르고있는 것입니다 *는 와일드 카드입니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.