web-dev-qa-db-ja.com

bash /標準のLinuxコマンドのみを使用して文字列内の一重引用符と二重引用符を削除する

Bash /標準のLinuxコマンドのみを使用して、文字列を次のように翻訳するものを探しています。

  1. 文字列を囲む一重引用符は削除する必要があります
  2. 文字列を囲む二重引用符は削除する必要があります
  3. 引用符で囲まれていない文字列は同じままである必要があります
  4. 周囲の引用符が一致しない文字列は同じままにする必要があります
  5. 文字列を囲まない一重引用符はそのままにしておく必要があります
  6. 文字列を囲まない二重引用符はそのままにしておく必要があります

例えば:

  • 「食べ物」は食べ物になるはずです
  • 「食べ物」は食べ物になるはずです
  • 食べ物は同じままでなければなりません
  • 「食べ物」は同じままである必要があります
  • 「食べ物」は同じままでなければなりません
  • 'Fo'od'はFo'odになるはずです
  • 「Fo'od」はFo'odになるはずです
  • Fo'odは同じままである必要があります
  • 'Fo "od'はFo" odになるはずです
  • 「Fo "od」はFo" odになるはずです
  • Fo "odは同じままである必要があります

ありがとうございました!

20
Jason

これはそれを行う必要があります:

sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt

In.txtは次のとおりです。

"Fo'od'
'Food'
"Food"
"Fo"od'
Food
'Food"
"Food'
'Fo'od'
"Fo'od"
Fo'od
'Fo"od'
"Fo"od"
Fo"od

そしてexpected.txtは次のとおりです。

"Fo'od'
Food
Food
"Fo"od'
Food
'Food"
"Food'
Fo'od
Fo'od
Fo'od
Fo"od
Fo"od
Fo"od

それらが一致することを確認できます:

diff -s <(sed "s/^\([\"']\)\(.*\)\1\$/\2/g" in.txt) expected.txt
32
richq

trを使用できます:

echo "$string" | tr -d 'chars to delete' 

...も機能しますが、「tr」ははるかに古い(Redhat 9っぽい)ディストリビューションでは問題があることが知られています。 trは 'translate'の略語で、入力を変換するためにパイプで一般的に使用されます。 -dオプションは単に「削除」を意味します。

最新バージョンのほとんどには、上から下、下から上への変換、空白の削除などを行うための事前定義されたマクロも含まれています。したがって、これを使用する場合は、他に何が行われるかを確認してください(ヘルプ出力/マニュアルページを参照)。重宝します。

16
Tim Post
VAR="'FOOD'"

VAR=$(eval echo $VAR)

説明:引用符はシェルによってすでに理解されているため、自分で入力した場合と同じように、引用符で囲まれた文字列をエコーするコマンドを評価するようにシェルに依頼できます。

ここで、引用符は実際にはVARの値の一部であるため、eval echo $VAReval echo 'FOOD'に展開されます。シェルでecho 'FOOD'を実行すると、FOOD(引用符なし)が返されます。それがevalが行うことです。入力を受け取り、シェルコマンドのように実行します。

⚠コードインジェクション!

evalスクリプトをコードインジェクションにさらします。

VAR=';ls -l'

VAR=$(eval echo $VAR)

ls -lが実行されます。

ここには、さらに多くの有害なコードが挿入される可能性があります。

12
user3766095

あなたはおそらく使用したいと思うでしょうsed .. ..

echo $mystring | sed -s "s/^\(\(\"\(.*\)\"\)\|\('\(.*\)'\)\)\$/\\3\\5/g"
7
Varkhan

Bashビルトインを使用するだけです(つまり、Bashパラメーターの拡張):

IFS=' ' 

food_strings=( "'Food'" '"Food"' Food "'Food\"" "\"Food'" "'Fo'od'" "\"Fo'od\"" "Fo'od" "'Fo\"od'" '"Fo"od"' 'Fo"od'  )  

for food in ${food_strings[@]}; do 

   [[ "${food#\'}" != "$food" ]] && [[ "${food%\'}" != "$food" ]] && { food="${food#\'}"; food="${food%\'}"; } 

   [[ "${food#\"}" != "$food" ]] && [[ "${food%\"}" != "$food" ]] && { food="${food#\"}"; food="${food%\"}"; } 

   echo "$food"

done 

Bashパラメーター拡張のさらに別の例については、以下を参照してください。

http://codesnippets.joyent.com/posts/show/1816

4
bitty

これにも偶然出くわしました。最初の3つのテストケースでは、eval echo $stringうまく機能します。要求されたすべてのケースと他のいくつかのケースで機能させるために、私はこれを思いつきました(bashdashでテスト済み):

#!/bin/sh

stripquotes() {
    local firstchar="`substr "$1" 0 1`"
    local len=${#1}
    local ilast=$((${#1} - 1))
    local lastchar="`substr "$1" $(($len - 1))`"
    if [ "$firstchar" = '"' ] || [ "$firstchar" = "'" ] && [ $firstchar = $lastchar ]; then
        echo "`substr "$1" 1 $(($len - 2))`"
    else
        echo "$1"
    fi
}

# $1 = String.
# $2 = Start index.
# $3 = Length (optional). If unspecified or an empty string, the length of the
#      rest of the string is used.
substr() {
    local "len=$3"
    [ "$len" = '' ] && len=${#1}
    if ! (echo ${1:$2:$len}) 2>/dev/null; then
        echo "$1" | awk "{ print(substr(\$0, $(($2 + 1)), $len)) }"
    fi
}

var="'Food'"
stripquotes "$var"

var='"Food"'
stripquotes "$var"

var=Food
stripquotes "$var"

var=\'Food\"
stripquotes "$var"

var=\"Food\'
stripquotes "$var"

var="'Fo'od'"
stripquotes "$var"

var="\"Fo'od\""
stripquotes "$var"

var="Fo'od"
stripquotes "$var"

var="'Fo\"od'"
stripquotes "$var"

var="\"Fo\"od\""
stripquotes "$var"

var="Fo\"od"
stripquotes "$var"

# A string with whitespace should work too.
var="'F\"o 'o o o' o\"d'"
stripquotes "$var"

# Strings that start and end with the same character that isn't a quote or
# doublequote should stay the same.
var="TEST"
stripquotes "$var"

# An empty string should not cause errors.
var=
stripquotes "$var"

# Strings of length 2 that begin and end with a quote or doublequote should not
# cause errors.
var="''"
stripquotes "$var"
var='""'
stripquotes "$var"
2
Jelle Geerts
python -c "import sys;a=sys.stdin.read();a=a.strip();print (a[1:-1] if a[0]==a[-1] and a[0] in \"'\\\"\" else a)"

エッジケース(空の文字列など)をうまく処理できませんが、開始点として機能します。前後の文字が同じで、「」または「」の場合は、文字をストライピングすることで機能します。

1
cobbal