تجريد اقتباسات واحدة ومزدوجة في سلسلة باستخدام أوامر باش / قياسي Linux فقط

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

  •  09-09-2019
  •  | 
  •  

سؤال

أبحث عن شيء سوف يترجم سلسلة على النحو التالي، باستخدام أوامر باش / قياسية Linux فقط:

  1. يجب إزالة الاقتباسات المحيطة بالسلسلة
  2. يجب إزالة الاقتباسات المحيطة بسلسلة
  3. السلاسل غير المسددة يجب أن تظل هي نفسها
  4. يجب أن تظل سلاسل مع اقتباسات محيطة لا مثيل لها نفس الشيء
  5. يجب أن تبقى اقتباسات واحدة لا تحيط بالسلسلة
  6. علامات الاقتباس المزدوجة التي لا تحيط بالسلسلة يجب أن تبقى

علي سبيل المثال:

  • يجب أن يصبح "الطعام"
  • يجب أن يصبح "الطعام" الطعام
  • يجب أن يبقى الطعام هو نفسه
  • يجب أن يبقى "الطعام" هو نفسه
  • يجب أن يبقى "الطعام" هو نفسه
  • يجب أن تصبح 'fo'od' fo'od
  • يجب أن تصبح "fo'od" fo'od
  • يجب أن تظل fo'od هو نفسه
  • يجب أن تصبح "FO" OD "OD
  • يجب أن تصبح "FO" OD "
  • يجب أن تظل 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

والمتوقع.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 "يكون مشكلة في توزيعات أكبر سنا (Circa Redhat 9-ISH). tr هو اختصار ل "ترجمة"، يستخدم عادة في أنابيب لتحويل المدخلات. ال -d الخيار يعني ببساطة "حذف".

تحتوي معظم الإصدارات الحديثة أيضا على وحدات ماكرو محددة مسبقا لتحويل العلوي إلى الأدنى، والسفلي إلى الأعلى، وقتل المساحة البيضاء، وما إلى ذلك. وبالتالي، إذا كنت تستخدمه، فاستقل ثانية إلى الكوخ في أي شيء يقوم به (انظر صفحة الإخراج / الرجل)، تأتي في متناول اليدين.

VAR="'FOOD'"

VAR=$(eval echo $VAR)

Explanation: نظرا لأن الاقتباسات مفهومة بالفعل من قبل قذيفة، يمكنك طرح القشرة لتقييم أمر فقط صدى السلسلة المعروضة، بنفس الطريقة التي تقوم بها عند كتابة ذلك بنفسك.

هنا، eval echo $VAR يتوسع إلى eval echo 'FOOD' لأن الاقتباسات هي في الواقع جزء من قيمة VAR. وبعد إذا كنت لتشغيل echo 'FOOD' في قذيفة سوف تحصل عليها FOOD (بدون اقتباس). وهذا ما eval هل: يأخذ مدخلاتها وتشغيلها مثل أمر Shell.

⚠code حقن!

eval فضح البرامج النصية إلى قانون الحقن.

VAR=';ls -l'

VAR=$(eval echo $VAR)

سوف تسبب تنفيذ ls -l.

يمكن أن يتم حقن رموز أكثر ضارة هنا.

ربما تريد استخدام سيد...

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

فقط باستخدام Bash Sendins (أي توسيع المعلمة IE 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.

تعثرت فقط على هذا أيضا. للحالات الثلاثة الأولى، eval echo $string يعمل جيدا. للحصول عليه للعمل لجميع الحالات المطلوبة وعدد قليل من الآخرين، توصلت إلى هذا (اختباره bash و dash):

#!/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