Besoin d'insert des guillemets simples dans le file text à utiliser comme requête SQL à l'aide de sed

J'ai créé une ligne de text qui ressemble à ceci:

INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept); 

Je veux utiliser sed pour le faire ressembler à ceci:

 INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

J'ai essayé d'échapper aux ' multiples façons et je suis si près d'get ce que je ressens mais j'ai besoin d'un peu d'aide pour l'get là-bas.

Cela a plus de sens dans le context et je suis un peu plus loin au cours des 17 dernières heures (apparemment)

 #!/bin/bash ssh ubnt@xxx.xxx.xxx.xxx brmacs >>MACS.txt mv MACS.txt /etc/persistent scp mhalls@xxx.xxx.xxx.xxx:/etc/persistent/MACS.txt MACS.txt sed -i "1d" MACS.txt head -c 58 MACS.txt >>shortmacs.txt tail -c 18 shortmacs.txt >>usermac.txt sed 's/"//g' usermac.txt >>usermacrdy.txt sed -i 's/^/INSERT INTO `radcheck`(`id`, `username`, `atsortingbute`, `op`, `value`) VALUES (,'',/' usermacrdy.txt sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt sed -i "s/,,/\,\'\',\'/" sqlquery.txt rm -f MACS.txt rm -f shortmacs.txt rm -f usermac.txt rm -f usermacrdy.txt 

TRAVAUX!!!

La tête et la queue coupent l'adresse MAC du file text d'origine à partir du périphérique UBNT CPE et ensuite je le transmets à sed pour build la syntaxe SQL autour de l'adresse MAC.

Après tout ce que j'ai découvert la partie d' id de la requête n'est pas nécessaire pour le succès alors maintenant je suis légèrement dans le même bateau avec:

 sed -i 's/^/INSERT INTO `radcheck`(`username`, `atsortingbute`, `op`, `value`) VALUES (/' usermacrdy.txt sed "s/$/','Auth-Type',':=','Accept');/" usermacrdy.txt > sqlquery.txt sed -i "s/\,\'\',\'//" sqlquery.txt 

Merci pour toutes les réponses, je vais passer au crible chaque réparation du mieux que je peux !!!!!! ce forum est génial !!! : D: D: D

Il y a quatre façons d'inclure le guillemet simple dont vous avez besoin.

On ne peut pas échapper à une string à guillemets simples dans une string à guillemets simples. Cependant, vous pouvez mettre fin à la string citée, insert un guillemet simple échappé, puis démarrer une nouvelle string guillemets. Ainsi, pour mettre une seule citation au milieu de 'ab' , utilisez: 'a'\''b' . Ou, en utilisant la command sed dont vous avez besoin:

 $ sed -r 's/,([^ ),]+)/,'\''\1'\''/g; s/,,/,'\'\'',/g' file INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

La deuxième méthode consiste à utiliser une string entre guillemets, auquel cas le guillemet simple peut être inséré facilement:

 $ sed -r "s/,([^ ),]+)/,'\1'/g; s/,,/,'',/g" file INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

Ce problème avec les strings entre guillemets est que le shell effectue le traitement sur eux. Ici, cependant, il n'y a pas de caractères shell-actifs, donc c'est facile.

La troisième méthode consiste à utiliser un échappement hexadécimal tel que PM2Ring le démontre.

La quasortingème façon, suggérée dans les commentaires de Jonathan Leffler, est de placer les commands sed dans un file séparé:

 $ cat script.sed s/,([^ ),]+)/,'\1'/g s/,,/,'',/g $ sed -rf script.sed file INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

Cette façon de faire a le fort avantage que sed lit les commands directement sans aucune interférence de la coquille. Par conséquent, cela évite complètement la nécessité d'échapper aux caractères shell-actifs et permet d'entrer les commands dans la syntaxe pure sed .

Comment fonctionne la solution sed

L'astuce consiste à mettre des guillemets simples autour des strings séparées par des virgules que vous voulez, mais pas autour des autres. Basé sur le seul exemple que vous avez donné, voici une approche:

  • s/,([^ ),]+)/,'\1'/g

    Cela search un ou plusieurs caractères non-espace, non-virgule et non-proches-parens qui suivent une virgule. Ces caractères sont placés à l'intérieur de guillemets simples.

  • s/,,/,'',/g

    Cela search des virgules consécutives et place deux guillemets entre eux.

OSX et d'autres plates-forms BSD

Pour éviter les antislashs supplémentaires, les expressions sed ci-dessus utilisent des expressions régulières étendues. Avec GNU, ils sont appelés en -r mais, avec BSD, ils sont appelés avec -E . En outre, certains sed non-GNU n'acceptent pas plusieurs commands séparées par des points-virgules. Ainsi, sur OSX, essayez:

 sed -E -e "s/,([^ ),]+)/,'\1'/g" -e "s/,,/,'',/g" file 

Addendum: correspondance d'une adresse MAC

D'après les commentaires, nous avons les commentaires suivants;

 $ cat file3 INSERT INTO radcheck(username, atsortingbute, op, value) VALUES (00:23:32:c2:a9:e8,'Auth-Type',':=','Accept'); 

Et, nous voulons mettre des guillemets autour de l'adresse MAC qui suit le open-parens. Pour faire ça:

 $ sed -r "s/\(([[:xdigit:]:]+)/('\1'/" file3 INSERT INTO radcheck(username, atsortingbute, op, value) VALUES ('00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

Dans n'importe quelle locale, [:xdigit:] correspondra à n'importe quel chiffre hexadécimal. Ainsi, ([[:xdigit:]:]+) correspondra à une adresse MAC (chiffre hexadécimal ou deux-points).

Lorsque vous travaillez à l'échelle mondiale, vous devez tenir count de la façon dont vous lisez. Une substitution globale va split un espace de motif en champs individuels délimités selon vos spécifications et fonctionner sur chacun d'eux. Les délimiteurs sont reconnus de gauche à droite – dans l'ordre où ils sont lus – et sed appliquera chaque action dès qu'elle le pourra. Voici une déclaration unique s/// ubstitution qui peut faire ce que vous requestz:

 sed "s/\(([^)]*)[^,]*\)\{0,1\},\([^,)]*\)/\1,'\2'/g " <<\IN INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept); 

Lorsqu'il est exécuté, cela imprime:

 INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 

Voici comment:

  • \(([^)]*)[^,]*\)\{0,1\} – Le plus important est la dissortingbution de * zero + matches et de l'autre. Ce bloc entier est facultatif – sed finda heureusement une string nulle à sa place count tenu de l'opportunité – et cela fait beaucoup de time, sinon cela ne fonctionnerait pas du tout. Mais parce que \{0,1\} est utilisé sed ne correspondra pas à plus d'une séquence entière comme celle-ci. Et c'est pourquoi la dissortingbution est importante. Dans ce bloc, nous avons:
    • ( – au less un paren à gauche.
    • [^)]* – zéro + pas-droit parens.
    • ) – un paren droit
    • [^,]* – zéro + pas-virgules.
  • sed va correspondre à chacun d'eux dans l'ordre – et comme un bloc parce qu'ils sont \( groupé \) . La correspondance * zéro + est très importante dans le monde – si vous utilisez + au less un dans ce paramètre, vous réduisez considérablement l' efficacité de vos modifications appliquées. Pour juste l'input du bloc ci-dessus, sed délimite ainsi votre string:

  • INSERT INTO radcheck – Cette string vient avant un de nos matchs et ne contient aucun d'entre eux. Il est ignoré.

  • (id, username, atsortingbute, op, value) VALUES ( – Cette string constitue notre entier * bloc de correspondance optionnel. toute la string de [^,]* qui nous transporte audelà d' un autre cas de correspondance pour ( . Il ne peut pas maintenant correspondre – et ainsi sauter – le suivant.

Et tandis que sed applique les rlocations pour \2 sur la seconde (.,.,.) , Il appliquera toujours des rlocations pour \1 aussi parce qu'il correspond toujours \1 . J'ai d'abord apparié \1 comme entier (.,.,.)..( bloc, l'a enregistré dans \1 et l'a remplacé par \1 – avec lui-même. remplacez \1 par une string vide à chaque fois qu'il correspond à un – qui correspond à chaque fois qu'il correspond à une virgule.

Étant donné de nombreuses séquences de ce type sur une ligne – et étant donné que les virgules ne se produisent que dans les délimiteurs ( ) , sed alternera les guillemets pour chaque séquence. Voici votre échantillon plusieurs fois:

 INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept');INSERT INTO radcheck(id, username, atsortingbute, op, value) VALUES (,'','00:23:32:c2:a9:e8','Auth-Type',':=','Accept'); 
  • ,\([^,)]*\) – notez que la seule correspondance non optionnelle pour l'expression entière est la virgule. L'autre bloc se produit avant lui dans l'expression et en input et donc sed permet d'appliquer – mais la virgule est prioritaire quand tout le rest est égal, et c'est la seule raison pour laquelle sed pas partout les strings nulles entre chaque octet sur les deux autres blocs ne correspondent pas à une string nulle en appliquant – sed délimite sur elle.
  • sed continuera à correspondre à \2 – et à sauvegarder – chaque séquence de caractères qui ne le sont pas ) et non,. Il replacea chaque virgule avec celle-ci ,'\2' . Il continuera de cette façon jusqu'à ce qu'il rencontre ( à quel point il sera capable de remplir \1 et ainsi le fera.

Essaye ça:

sed 's/,,/,\x27\x27,/'

\x27 est le code d'échappement hexadécimal pour '

démo

 $ echo 'INSERT INTO `radcheck`(`id`, `username`, `atsortingbute`, `op`, `value`) VALUES (,,00:23:32:c2:a9:e8,Auth-Type,:=,Accept);' | > sed 's/,,/,\x27\x27,/' INSERT INTO `radcheck`(`id`, `username`, `atsortingbute`, `op`, `value`) VALUES (,'',00:23:32:c2:a9:e8,Auth-Type,:=,Accept);