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


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.