citations sed et backslashes sur cygwin

1

J'essaye d'extraire une chaîne d'une chaîne avec sed sur cygwin.

#!/bin/bash

var1="foo\ bar"
var2="baz"

var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | sed "s/"$var1"//"`
echo "$var4"

mais j'obtiens la sortie suivante, provoquée par la barre oblique inverse:     sed: -e expression # 1, char 6: commande `s 'non terminée

comment puis-je écrire la commande sed pour sortir 'baz'?

elSnape
la source

Réponses:

2

Le problème est que tant la coque que sed interpréter les barres obliques inverses. Vous pouvez peut-être obtenir sed pour le faire correctement, mais je recommanderais simplement d'utiliser un outil différent, par exemple Perl:

#!/bin/bash
export var1="foo\ bar" ## The export allows Perl to access the variable as $ENV{var1}
var2="baz"
var3="$var1 $var2"

# extract "foo\ bar" from "foo\ bar baz"
var4=`echo $var3 | perl -ne '$var1=quotemeta($ENV{var1}); s/$var1//; print'`
echo "$var4"

L'exemple ci-dessus utilise Perl quotemeta fonction qui échappe à tous les caractères non-ASCII, permettant à l'expression régulière de correspondre correctement à la barre oblique inverse

Enfin, pourquoi voulez-vous faire cela? Avez-vous vraiment besoin de faire correspondre le \ ou essayez-vous de faire correspondre les espaces dans les chaînes bash? Il y a des moyens plus faciles si oui.

terdon
la source
1
Le script Perl peut être un peu joué au golf: perl -pe "s/\Q$var1//"
glenn jackman
@ glennjackman nice! Je suppose que le \ Q est un raccourci pour quotemeta? Je ne changerai pas la réponse car c'est plus clair tel quel, mais c'est bon à savoir, merci.
terdon
1

Pour le dire simplement ... sed ne fonctionne pas ... comme sur les colonnes, c'est une approche plus orientée ligne. Ne forcez pas une commande - utilisez-la où cela convient. Couper serait une option meilleure / plus simple

sinon, si l'extraction de sous-chaîne est ce que vous recherchez, awk convient également pour cela ... exemple

Kaizen ~/so_test
$ echo "foo\ bar baz" | awk '{print substr($0,1,8)}'
+ echo 'foo\ bar baz'
+ awk '{print substr($0,1,8)}'
foo\ bar

son plus simple à utiliser dans ce cas, cela suffit-il?

n13
la source
0

Pour que cela fonctionne avec sed, nous devons échapper aux barres obliques inverses. Préparez-vous à la folie:

$ echo "$var1"
foo\ bar
$ echo "$var3"
foo\ bar baz
$ echo "$var3" | sed "s/$var1//"
foo\ bar baz
$ echo "${var1//\\/\\\\}"
foo\\ bar
$ echo "$var3" | sed "s/${var1//\\/\\\\}//"
 baz

Bien sûr, il y a beaucoup d'autres personnages qui nécessitent une évasion, tels que *La réponse en perl de @ terdon est donc meilleure que cette forêt de cure-dents.

glenn jackman
la source