쉘 스크립트-변수에서 첫 번째와 마지막 따옴표 ( ") 제거


225

다음은 더 큰 스크립트의 쉘 스크립트 스 니펫입니다. 변수가 보유한 문자열에서 따옴표를 제거합니다. sed를 사용하여하고 있지만 효율적입니까? 그렇지 않다면 효율적인 방법은 무엇입니까?

#!/bin/sh

opt="\"html\\test\\\""
temp=`echo $opt | sed 's/.\(.*\)/\1/' | sed 's/\(.*\)./\1/'`
echo $temp

을 사용하는 것이 좋습니다 sed "s/^\(\"\)\(.*\)\1\$/\2/g" <<<"$opt". 이 구문은 일치하는 쌍이있는 경우에만 qoutes를 제거합니다.
— John Smith

@JohnSmith 또한 셸 스크립트에서 자동으로 따옴표를 이스케이프해야하지만 일치하는지 여부에 관계없이 그렇게해야하므로 게시 한 표현식을 사용하지 않을 것입니다.
— Pysis

모든 따옴표를 제거하고 싶을 때이 질문을 발견 한 경우 다음 답변을 참조하십시오 : askubuntu.com/a/979964/103498 .
— 고든 빈

답변:


268

기본 셸 접두사 / 접미사 제거 기능을 사용하면 더 간단하고 효율적인 방법이 있습니다.

temp="${opt%\"}"
temp="${temp#\"}"
echo "$temp"

${opt%\"}접미사를 제거합니다 "(쉘 해석을 방지하기 위해 백 슬래시로 이스케이프 처리).

${temp#\"}접두사를 제거합니다 "(쉘 해석을 방지하기 위해 백 슬래시로 이스케이프 처리).

또 다른 장점은 주변 인용 부호가있는 경우에만 주변 인용 부호를 제거한다는 것입니다.

BTW, 솔루션은 항상 첫 번째 문자와 마지막 문자를 제거합니다 (물론 데이터를 알고 있다고 확신하지만 제거하는 것을 항상 확인하는 것이 좋습니다).

sed 사용하기 :

echo "$opt" | sed -e 's/^"//' -e 's/"$//'

(jfgagne에서 표시 한대로 에코를 제거하는 개선 된 버전)

sed -e 's/^"//' -e 's/"$//' <<<"$opt"

따라서 선행 "은 아무것도 아닌 것으로 바꾸고 후미도 아무것도 아닌 것으로 바꿉니다 ". 동일한 호출에서 (다른 sed를 파이프하고 시작할 필요가 없습니다. 사용 -e하면 여러 개의 텍스트 처리가 가능합니다).


14
를 사용하여 sed 솔루션에서 파이프를 제거 할 수 있습니다 sed -e 's/^"//' -e 's/"$//' <<< $opt.
— jfg956

1
문자열에 선행 및 후행 따옴표 문자가 모두 없으면 잘못 작동 할 수 있습니다. 정상적으로 처리하기위한 제안 사항이 있습니까?
— jsears

일치하는 외부 따옴표 만 처리하려면 @Joachim Pileborg의 답변을 참조하십시오
— jsears

1
@jsears 허? 이것은 특별히 시작부터 하나를, 끝에서 하나를 있다면 다듬습니다. 둘 다 존재하지 않는 한 제거하지 않으려는 경우; 예, 하나의 sed정규 표현식을 사용하거나 변수 대체를 줄 바꿈case $opt in '"'*'"') ... do it ... ;; esac
— Tripleee

2
sed 's/^"\|"$//g'
— tzrlk

287

tr 을 사용 하여 삭제하십시오 ".

 echo "$opt" | tr -d '"'

참고 : 이것은 앞뒤뿐만 아니라 모든 큰 따옴표를 제거합니다.


16
OP가 요구 한 것은 아닙니다. 앞뒤 인용뿐만 아니라 모든 따옴표도 제거하기 때문입니다.
— Lenar Hoyt

19
OP에 명시 적으로 응답하지 않더라도 "/ path / file-name"의 시작과 끝에 큰 따옴표 만 있기 때문에이 문제가 해결됩니다. 큰 따옴표가 포함되어 있지 않습니다. +1
— WinEunuuchs2Unix

6
이 솔루션은 많은 사람들이 원하는 것입니다. 대부분의 경우 스크립팅은 실행 가능한 데이터를 따옴표로 묶은 문자열로 쉽게 가져올 수 있습니다.
— Shadoninja

2
우아하고 더 많은 시행 착오 디버그 시간에서 나를 구했습니다. 고마워.
— 스콧 웨이드

이것은 이상적으로 원하는 것이므로 허용되는 답변보다 더 많은 표를 얻는 이유입니다.
— apurvc

38

이렇게하면 큰 따옴표가 모두 제거됩니다.

echo "${opt//\"}"

1
그러나 이스케이프 된 따옴표로 묶습니다 (예 :) Don't remove this \" quote. :-(
— gniourf_gniourf

이것은 Bash 확장이므로 일반적으로 쉘 스크립트에는 적용되지 않습니다. (이것이 중요한지 아닌지에 대해서는 의문이 모호하다. 구글에서 이것을 찾는 방문자는 POSIX 솔루션을 찾고있을 것이다.)
— tripleee

완전! 정확히 내가 필요한 것. 나는 OP가 요청한 것만이 아니라 많은 답변을 제공하는 이와 같은 질문을 좋아합니다. 보석은 받아 들여지지 않은 답변에 있습니다!
— dlite922

OP는 선행 / 후행 따옴표 만 제거하고 이스케이프 된 따옴표를 유지하는 것을 원합니다.
— 페르난도 파스

36

xargs를 사용하는 간단한 방법이 있습니다 .

> echo '"quoted"' | xargs
quoted

명령이 제공되지 않으면 xargs 는 echo를 기본 명령으로 사용하고 입력에서 따옴표를 제거합니다. 예를 들어 여기를 참조 하십시오 .


echo '"quoted"' | xargs -> quoted
— kyb

1
이것은 작동하지만 문자열의 짝수 따옴표에만 적용됩니다. 홀수가 있으면 오류가 발생합니다.
— James Shewey


19

가장 짧은 방법 -시도 :

echo $opt | sed "s/\"//g"

실제로 모든 "s (큰 따옴표)를 제거합니다 ( opt처음과 끝이 아닌 다른 큰 따옴표가 실제로 있습니까? 그래서 실제로는 똑같은 것입니다. ;-)


4
큰 따옴표를 모두 제거하려면 "$ {opt // \"/} "를 사용하는 것이 좋습니다. 파이프, 서브 쉘 없음 ... opt에 공백이 있으면 잃어 버릴 수 있습니다. echo "$ opt"
— huelbois

글쎄, 변수는 기본적으로 httpd의 구성 파일에서 DocumentRoot의 경로를 읽으므로 따옴표 문자가 문자열에있을 수 있다고 생각하지 않습니다. 그리고이 sed는 훨씬 깔끔하고 효율적입니다 .... 감사합니다!
— user1263746

16

jq를 사용하고 결과에서 따옴표를 제거하려고하면 다른 답변이 효과가 있지만 더 좋은 방법이 있습니다. -r옵션 을 사용하면 따옴표없이 결과를 출력 할 수 있습니다.

$ echo '{"foo": "bar"}' | jq '.foo'
"bar"

$ echo '{"foo": "bar"}' | jq -r '.foo'
bar

나는 사용하고 jq있지만 jq도 ASCII 출력을 출력하는 경우 작동하지 않는다는 점에 유의하십시오 -a(jq 측 버그입니다)
— Can Poyrazoğlu

yq또한이 -r옵션을 :yq -r '.foo' file.yml
— Hlib Babii 보낸

12

최신 정보

bash / 표준 Linux 명령 만 사용하여 문자열에서 작은 따옴표와 큰 따옴표를 제거하는 간단하고 우아한 대답 :

BAR=$(eval echo $BAR)에서 따옴표를 제거합니다 BAR.

===================================================== ===========

hueybois의 답변을 바탕으로 많은 시행 착오 끝에이 기능을 생각해 냈습니다.

function stripStartAndEndQuotes {
    cmd="temp=\${$1%\\\"}"
    eval echo $cmd
    temp="${temp#\"}"
    eval echo "$1=$temp"
}

아무것도 인쇄하지 않으려면 에바를로 파이프 할 수 있습니다 /dev/null 2>&1.

용법:

$ BAR="FOO BAR"
$ echo BAR
"FOO BAR"
$ stripStartAndEndQuotes "BAR"
$ echo BAR
FOO BAR

1
나는 단순하고 우아한 것을 정말로 좋아하지만 eval은 큰 따옴표를 자르지 않고 실제로 코드 줄로 평가한다는 점에 주목할 가치가 있다고 생각합니다. 따라서이 기술은 BAR에 쉘이 대체 할 수있는 다른 시퀀스를 포함 할 때 예기치 않은 결과를 초래할 수 있습니다 (예 : BAR = \ 'abc \'또는 BAR = ab \ 'c 또는 BAR = a \ $ b 또는 BAR = a \ $ (ls *))
— MaxP

11

Bash에서 가장 쉬운 솔루션 :

$ s='"abc"'
$ echo $s
"abc"
$ echo "${s:1:-1}"
abc

이것을 부분 문자열 확장이라고합니다 ( Gnu Bash 매뉴얼 참조 및 검색 ${parameter:offset:length}). 이 예제에서는 하위 문자열이 s위치 1 에서 시작하여 두 번째 마지막 위치에서 끝나는 것을 가져옵니다 . 이는 경우는 사실이다 length음의 값입니다 뒤로가의 끝에서 오프셋 실행으로 해석됩니다 parameter.


bash v4.2에서 지원되는 음의 길이
— mr.spuratic

8

이것은 sed를 사용하지 않고 가장 개별적인 방법입니다.

x='"fish"'
printf "   quotes: %s\nno quotes:  %s\n" "$x" "${x//\"/}"

또는

echo $x
echo ${x//\"/}

산출:

   quotes: "fish"
no quotes:  fish

나는 이것을 출처 에서 얻었다 .


문자열 내에서 따옴표를 둘러싼 따옴표를 제거합니다.
— jsears

해설을 제외하고 이것은 2012의 @StevenPenny의 답변 과 동일합니다 .
— tripleee


2

내 버전

strip_quotes() {
    while [[ $# -gt 0 ]]; do
        local value=${!1}
        local len=${#value}
        [[ ${value:0:1} == \" && ${value:$len-1:1} == \" ]] && declare -g $1="${value:1:$len-2}"
        shift
    done
}

이 함수는 변수 이름을 받아들이고 따옴표를 제거합니다. 일치하는 선행 및 후행 따옴표 쌍만 제거합니다. 후행 따옴표가 이스케이프되는지 확인하지 않습니다 (\ 나오는 이스케이프되지 않음).

내 경험상, 이와 같은 범용 문자열 유틸리티 기능 (라이브러리가 있음)은 문자열을 직접 조작하거나 패턴 일치를 사용하지 않고 특히 하위 쉘을 만들거나 외부 도구를 호출하지 않을 때 가장 효율적입니다 sed, awk또는 grep.

var1="\"test \\ \" end \""
var2=test
var3=\"test
var4=test\"
echo before:
for i in var{1,2,3,4}; do
    echo $i="${!i}"
done
strip_quotes var{1,2,3,4}
echo
echo after:
for i in var{1,2,3,4}; do
    echo $i="${!i}"
done

0

나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 여기에 다른 sed 변형이있어 누군가에게 유용 할 수 있습니다. 다른 것들 중 일부와 달리 시작이나 끝에서 큰 따옴표 만 대체합니다 ...

echo "$opt" | sed -r 's/^"|"$//g'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.