剥離、単一および二重引用符文字列を使用bashの標準Linuxコマンドのみ

StackOverflow https://stackoverflow.com/questions/758031

  •  09-09-2019
  •  | 
  •  

質問

を探しているもの翻訳の文字列としており、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引き続きそうあるべきであると同

感謝です。

役に立ちましたか?

解決

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

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

他のヒント

あなたはtrを使用することができます:

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

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

最近のほとんどのバージョンでは、上部に低く、下に上位変換する定義済みマクロが含まれている、あなたはそれを使用する場合、それがない他に何で突く秒かかり、そこでなど、ホワイトスペースを殺す(ヘルプ出力/男を参照してくださいページ)、便利です。

VAR="'FOOD'"

VAR=$(eval echo $VAR)

説明:引用符はすでにシェルによって理解されているので、あなただけの引用符で囲まれた文字列、それがないのと同じ方法をエコー表示コマンドを評価するためにシェルを依頼することができ、あなたはそれを自分で入力すると、

ここで、eval echo $VARは引用符が実際にeval echo 'FOOD'の値の一部であるため、VARに拡張されます。あなたがシェルにecho 'FOOD'を実行した場合、あなたは(引用符なし)FOODを取得したいです。それはevalが何をするかだ。それは、その入力を受け取り、シェルコマンドのようにそれを実行します。

  

⚠CODEのINJECTION!

     

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

     
VAR=';ls -l'

VAR=$(eval echo $VAR)
     

ls -lの実行の原因になります。

     

さらに多くの有害なコードはここに注入することができます。

おそらく使いたい sed...

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

ちょうどバッシュビルトインを使用して(すなわち、バッシュパラメータ拡張)

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 

バッシュパラメータ展開のさらに別の例を参照:

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

ただ、同様にこのつまずきました。最初の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"
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)"

これは、(例えば、空の文字列のような)非常によくエッジケースを処理しないが、それは出発点となります。それは彼らが同じであれば、フロントとバックの文字をストライピングすることで動作し、それらがある場合」または「

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top