Suite

Utiliser uniquement une partie de la chaîne de substitution de variable en ligne dans ModelBuilder ?

Utiliser uniquement une partie de la chaîne de substitution de variable en ligne dans ModelBuilder ?


J'utilise une substitution de variable en ligne pour modifier un nom de champ. Je le fais dans un modèle d'itération dans le générateur de modèles. La variable en ligne est le nom de la classe d'entités que j'utilise comme entrée pour chaque itération. Lorsque je modifie le nom du champ, je souhaite n'utiliser que la première partie de la variable en ligne. Pour expliquer cela un peu mieux, voici la structure des noms de mes classes d'entités :

  • SA_05_Marche_CBR
  • SA_10_Marche_CBR
  • SA_05_Bike_CBR
  • SA_10_Bike_CBR
  • SA_05_Driv_CBR
  • SA_10_Driv_CBR
  • SA_05_Walk_PJC
  • SA_10_Marche_PJC
  • SA_05_Bike_PJC
  • SA_10_Bike_PJC
  • SA_05_Driv_PJC
  • SA_10_Driv_PJC
  • etc.

(Notez que tous les noms de classes d'entités ont exactement le même nombre de caractères pour chaque partie des noms)

Dans mon itérateur, ces noms de classes d'entités représentent ma chaîne de substitution de variable en ligne (appelée "count_field" dans mon modèle, voir l'image).

Lorsque j'utilise l'itérateur, je joins tous les SA_xx_xxxx avec une classe d'entités ponctuelles où j'utilise les trois dernières lettres du nom de la classe d'entités comme joker (par exemple "star_CBR"). Pour ma prochaine itération, je fais exactement la même chose, mais en utilisant "star_PJC" comme nouveau caractère générique. Ces itérations fonctionnent bien sans aucun problème et c'est aussi la raison pour laquelle mes classes d'entités doivent se terminer par "*_xxx".

Ensuite, dans mon itération, je modifie un certain nom de champ afin qu'ils puissent être différenciés dans la table de la classe d'entités. Actuellement, j'utilise cette substitution de variable en ligne pour renommer le champ (par exemple, "SJ_Count_%count_field%"). Aussi ce processus fonctionne très bien. Voici une image de la fenêtre de modification du champ :

(Veuillez ignorer la marque d'explication; cette image est pure pour une démo)

Ce que je veux faire, cependant, c'est qu'il n'utilise que partie de la variable en ligne pour modifier mon nom de champ. Les 4 dernières lettres de ma variable en ligne (par exemple "_CBR") peuvent être supprimées dans mon nouveau nom de champ. Ainsi, un nom de champ serait appelé, par exemple, "SJ_Count_SA_05_Bike"

J'ai à nouveau essayé de renommer mon nom de champ, mais je n'ai pas trouvé le moyen de supprimer les 4 derniers caractères via une itération. Quelqu'un a-t-il une idée de comment je pourrais le faire de manière efficace? L'utilisation de python dans l'outil alter field ne semble pas être une option (comme le montre l'image de la fenêtre de l'outil alter field). Voici une photo de mon modèle :


Utilisez l'outil Calculer la valeur dans le générateur de modèles pour supprimer les quatre derniers caractères de votre Nombre_Champ variable. Définissez l'outil comme condition préalable à l'outil de modification de champ pour vous assurer qu'il s'exécute en premier.

Définissez votre expression comme indiqué ci-dessous


Déclarer la variable en ligne à utiliser avec la substitution de paramètres

Je voudrais un moyen fiable d'obtenir le nom du répertoire où réside un script. J'aimerais que cette approche fonctionne également lorsqu'elle est appelée à partir du même répertoire (la plupart des cas d'utilisation impliquant dirname renverraient "." dans ce cas). Voici une de ces approches :

La logique est assez simple. déplacez-vous dans le répertoire du script, appelez pwd à partir de là, puis supprimez tout sauf le nom du répertoire final. Cependant, je n'arrive pas à comprendre la syntaxe pour le convertir en une ligne. J'aimerais de l'aide pour le faire.


Première phrase de la proposition :

&rdquo Le spécificateur en ligne peut être appliqué aux variables ainsi qu'aux fonctions.

L'effet garanti de l'inline appliqué à une fonction est de permettre à la fonction d'être définie à l'identique, avec un lien externe, dans plusieurs unités de traduction. Pour la pratique, cela signifie définir la fonction dans un en-tête, qui peut être inclus dans plusieurs unités de traduction. La proposition étend cette possibilité aux variables.

Ainsi, en termes pratiques, la proposition (maintenant acceptée) vous permet d'utiliser le mot-clé inline pour définir une variable de portée d'espace de noms const de liaison externe, ou tout membre de données de classe statique, dans un fichier d'en-tête, de sorte que les multiples définitions qui en résultent lorsque cet en-tête est inclus dans plusieurs unités de traduction sont OK avec l'éditeur de liens &ndash qu'il choisit juste un d'eux.

Jusqu'à et y compris C++14, la machinerie interne pour cela était là, afin de prendre en charge les variables statiques dans les modèles de classe, mais il n'y avait aucun moyen pratique d'utiliser cette machinerie. Il fallait recourir à des trucs comme

À partir de C++17, je crois qu'on peut écrire simplement

La proposition comprend le libellé

&rdquo Un membre de données statiques en ligne peut être défini dans la définition de classe et peut spécifier une ​accolade-or-equal-initializer. Si le membre est déclaré avec le spécificateur constexpr, il peut être redéclaré dans la portée de l'espace de noms sans initialiseur (cette utilisation est déconseillée ; voir ​ D.X). Les déclarations d'autres membres de données statiques ne doivent pas spécifier un ​accolade-or-égal-in‌​itialiseur

&hellip qui permet de simplifier davantage ce qui précède à juste

&hellip comme noté par T.C dans un commentaire à cette réponse.

De plus, le spécificateur constexpr implique en ligne pour les membres de données statiques ainsi que pour les fonctions.

Remarques:
¹ Pour une fonction, inline a également un effet d'indication sur l'optimisation, que le compilateur devrait préférer remplacer les appels de cette fonction par une substitution directe du code machine de la fonction. Cette indication peut être ignorée.


1 réponse 1

Vous avez le bon outil pour le travail, coupez, mais vous le rendez beaucoup plus compliqué que vous n'en avez besoin. Il n'y a absolument aucune raison d'utiliser une boucle bash ici, cela rend les choses plus lentes et plus compliquées. cut traitera chaque ligne du fichier par lui-même. Cependant, le délimiteur par défaut pour cut est une tabulation, pas un espace, vous devez donc lui dire de couper sur les espaces à l'aide de l'indicateur -d. Ensuite, au lieu de lui dire de couper des caractères spécifiques, dites-lui simplement d'imprimer le premier domaine avec -f 1 :

Avec sed , vous essaieriez de tout supprimer après le premier espace :

Ou, vous pouvez utiliser awk qui se divise en champs sur les espaces par défaut :

Vous pouvez même le faire dans le shell, mais ce sera beaucoup plus lent pour les fichiers plus volumineux et ce n'est généralement pas une bonne idée :


Mettre à jour

Avec ES6, vous pouvez également faire ceci :

J'ai écrit une fonction qui résout précisément le problème.

Premier argument est la chaîne que l'on voulait paramétrer. Vous devriez mettre vos variables dans cette chaîne comme ce format "%s1, %s2, . %s12".

Autres arguments sont les paramètres respectivement pour cette chaîne.

Si la position de la variable change dans cette chaîne, cette fonction la prend également en charge sans modifier les paramètres de la fonction.


La description

Les littéraux de modèle sont entourés du caractère backtick (` `) (accent grave) au lieu de guillemets doubles ou simples.

Les littéraux de modèle peuvent contenir des espaces réservés. Ceux-ci sont indiqués par le signe dollar et les accolades ( $ < expression >). Les expressions dans les espaces réservés et le texte entre les backticks (` `) sont passés à une fonction.

La fonction par défaut concatène simplement les parties en une seule chaîne. S'il y a une expression précédant le modèle littéral ( balise ici), cela s'appelle un . Dans ce cas, l'expression de balise (généralement une fonction) est appelée avec le modèle littéral, que vous pouvez ensuite manipuler avant de sortir.

Pour échapper à un backtick dans un modèle littéral, placez une barre oblique inverse ( ) avant le backtick.

Chaînes multilignes

Tous les caractères de saut de ligne insérés dans la source font partie du littéral du modèle.

En utilisant des chaînes normales, vous devrez utiliser la syntaxe suivante pour obtenir des chaînes multilignes :

En utilisant des littéraux de modèle, vous pouvez faire la même chose comme ceci :

Interpolation d'expressions

Afin d'incorporer des expressions dans des chaînes normales, vous utiliseriez la syntaxe suivante :

Maintenant, avec les littéraux de modèle, vous pouvez utiliser le sucre syntaxique, ce qui rend les substitutions comme celle-ci plus lisibles :

Modèles d'imbrication

Dans certains cas, l'imbrication d'un modèle est le moyen le plus simple (et peut-être le plus lisible) d'avoir des chaînes configurables. Dans un modèle backticked, il est simple d'autoriser les backticks internes en les utilisant à l'intérieur d'un espace réservé $ < > dans le modèle.

Par exemple, si la condition a est true , retournez ce littéral modélisé.

Dans ES2015 avec des littéraux de modèle et sans imbrication :

Dans ES2015 avec des littéraux de modèle imbriqués :

Modèles balisés

Une forme plus avancée de littéraux de modèle est tagué modèles.

Les balises vous permettent d'analyser les littéraux de modèle avec une fonction. Le premier argument d'une fonction de balise contient un tableau de valeurs de chaîne. Les arguments restants sont liés aux expressions.

La fonction tag peut alors effectuer toutes les opérations que vous souhaitez sur ces arguments et renvoyer la chaîne manipulée. (Alternativement, il peut renvoyer quelque chose de complètement différent, comme décrit dans l'un des exemples suivants.)

Le nom de la fonction utilisée pour la balise peut être celui que vous voulez.

Les fonctions de balise n'ont même pas besoin de renvoyer une chaîne !

Cordes brutes

La propriété spéciale raw, disponible sur le premier argument de la fonction tag, vous permet d'accéder aux chaînes brutes telles qu'elles ont été saisies, sans traiter les séquences d'échappement.

De plus, la méthode String.raw() existe pour créer des chaînes brutes, tout comme la fonction de modèle par défaut et la concaténation de chaînes le feraient.

Modèles balisés et séquences d'échappement

Comportement ES2016

Depuis ECMAScript 2016, les modèles balisés sont conformes aux règles des séquences d'échappement suivantes :

  • Les échappements Unicode commencent par " u ", par exemple u00A9
  • Les échappements de point de code Unicode indiqués par " u<> ", par exemple u
  • Échappements hexadécimaux commencés par " x ", par exemple xA9
  • Les échappements littéraux octaux commencent par " o " et sont suivis d'un ou plusieurs chiffres, par exemple o251

Cela signifie qu'un modèle balisé comme celui-ci est problématique, car, selon la grammaire ECMAScript, un analyseur recherche des séquences d'échappement Unicode valides, mais trouve une syntaxe mal formée :

ES2018 révision des séquences d'échappement illégales

Les modèles balisés devraient permettre l'intégration de langages (par exemple DSL ou LaTeX), où d'autres séquences d'échappement sont courantes. La proposition ECMAScript Template Literal Revision (étape 4, à intégrer dans la norme ECMAScript 2018) supprime la restriction syntaxique des séquences d'échappement ECMAScript des modèles balisés.

Cependant, les séquences d'échappement illégales doivent toujours être représentées dans la représentation « cuite ». Ils apparaîtront comme élément non défini dans le tableau « cooked » :

Notez que la restriction de séquence d'échappement n'est supprimée que de tagué modèles—pas de non tagué littéraux de modèle :


4 réponses 4

Le < n'est pas directement un aspect de la substitution de commandes bash. C'est un opérateur de redirection (comme un tube), que certains shells autorisent sans commande (POSIX ne précise pas ce comportement).

Ce serait peut-être plus clair avec plus d'espaces :

c'est effectivement* le même que le plus sûr POSIX

. ce qui est aussi efficace*

Commençons par cette dernière version. Cela exécute cat sans arguments, ce qui signifie qu'il lira à partir de l'entrée standard. $FILE est redirigé vers l'entrée standard en raison de < , donc cat met son contenu dans la sortie standard. La substitution $ (commande) pousse ensuite la sortie de cat dans des arguments pour echo .

Dans bash (mais pas dans le standard POSIX), vous pouvez utiliser < sans commande. bash (et zsh et ksh mais pas dash ) interprétera cela comme si cat < , mais sans invoquer un nouveau sous-processus. Comme cela est natif du shell, c'est plus rapide que d'exécuter littéralement la commande externe cat . *C'est pourquoi je dis "effectivement le même que".

$(<file) (fonctionne également avec `<file` ) est un opérateur spécial du shell Korn copié par zsh et bash . Cela ressemble beaucoup à une substitution de commande, mais ce n'est pas vraiment le cas.

Dans les shells POSIX, une commande simple est :

Toutes les parties sont facultatives, vous pouvez avoir des redirections uniquement, des commandes uniquement, des affectations uniquement ou des combinaisons.

S'il y a des redirections mais pas de commande, les redirections sont effectuées (un fichier > s'ouvre et tronque file ), mais rien ne se passe. Alors

Ouvre le fichier en lecture, mais rien ne se passe car il n'y a pas de commande. Le dossier est donc fermé et c'est tout. Si $(< file) était un simple substitution de commande, alors il s'étendrait à rien.

Dans la spécification POSIX, dans $(script) , si le script se compose uniquement de redirections, cela produit des résultats non spécifiés. C'est pour permettre ce comportement spécial du shell Korn.

En ksh (ici testé avec ksh93u+ ), si le script est constitué d'un et un seul commande simple (bien que les commentaires soient autorisés avant et après) qui consistent uniquement en des redirections (pas de commande, pas d'affectation) et si la première redirection est une redirection stdin (fd 0) en entrée uniquement ( < , << ou <<< ), donc :

  • $(< fichier)
  • $(0< fichier)
  • $(<&3) (également $(0>&3) en fait car c'est en fait le même opérateur)
  • $(< fichier > foo 2> $(quel que soit))
  • tous sauf la première redirection sont ignorés (ils sont analysés)
  • et il s'étend au contenu du fichier/heredoc/herestring (ou tout ce qui peut être lu à partir du descripteur de fichier si vous utilisez des choses comme <&3 ) moins les caractères de fin de ligne.

comme si vous utilisiez $(cat < file) sauf que

  • la lecture se fait en interne par le shell et non par cat
  • aucun tuyau ni processus supplémentaire n'est impliqué
  • en conséquence de ce qui précède, puisque le code à l'intérieur n'est pas exécuté dans un sous-shell, toute modification reste par la suite (comme dans $(<$) ou $(<file$((++n))) )
  • les erreurs de lecture (mais pas les erreurs lors de l'ouverture de fichiers ou de la duplication de descripteurs de fichiers) sont ignorées en silence.

Dans zsh , c'est la même chose sauf que ce comportement spécial n'est déclenché que lorsqu'il n'y a qu'une seule redirection d'entrée de fichier ( <file ou 0< file , no <&3 , <<<here , < a < b . )

Cependant, sauf lors de l'émulation d'autres shells, dans :

c'est quand il n'y a que des redirections d'entrée sans commandes, en dehors de la substitution de commandes, zsh exécute le $READNULLCMD (un pager par défaut), et quand il y a à la fois des redirections d'entrée et de sortie, le $NULLCMD ( cat par défaut), donc même si $(<&3) n'est pas reconnu comme cet opérateur spécial, il fonctionnera toujours comme dans ksh en invoquant un pager pour le faire (ce pager agissant comme un chat puisque sa sortie standard sera un tube).

Cependant, alors que le $(< a < b) de ksh s'étend au contenu de a , dans zsh , il s'étend au contenu de a et b (ou simplement b si l'option multios est désactivée), $(< a > b ) copierait a à b et s'étendrait à rien, etc.

bash a un opérateur similaire mais avec quelques différences :

les commentaires sont autorisés avant mais pas après :

comme dans zsh , une seule redirection de fichier stdin, bien qu'il n'y ait pas de recours à un $READNULLCMD , donc $(<&3) , $(< a < b) effectuent les redirections mais se développent à rien.

Dans bash , IFS= read -rd '' var < file (fonctionne également dans zsh ) est un moyen plus efficace de lire le contenu d'un texte fichier dans une variable. Il a également l'avantage de préserver les caractères de fin de ligne. Voir aussi $mapfile[file] dans zsh (dans le module zsh/mapfile et uniquement pour les fichiers normaux) qui fonctionne également avec les fichiers binaires.

Notez que les variantes de ksh basées sur pdksh présentent quelques variations par rapport à ksh93. D'intérêt, dans mksh (un de ces shells dérivés de pdksh), dans

est optimisé en ce que le contenu du document here (sans les caractères de fin) est étendu sans qu'un fichier temporaire ou un tube ne soit utilisé comme c'est le cas pour les documents here, ce qui en fait une syntaxe de citation multiligne efficace.

Pour être portable sur toutes les versions de ksh , zsh et bash , le mieux est de se limiter à seulement $(<file) en évitant les commentaires et en gardant à l'esprit que les modifications apportées aux variables peuvent ou non être conservées.


2 réponses 2

Suite à votre question précédente, il semble que vous vouliez tous les deux du texte non interprété et du texte interprété entrant dans un fichier. Dans ce cas, utilisez deux cat s (ou echo s) différents :

Il se passe deux ou trois choses ici : tout d'abord, la syntaxe heredoc avec << . Si vous incluez des guillemets dans cette chaîne de terminaison, comme dans la première ci-dessus, l'intégralité de la heredoc n'est pas interprétée - pas de paramètres ni de substitutions. Si tu ne pas utilisez des guillemets, comme dans le seconde cat ci-dessus, les variables comme $1 seront remplacées par leurs valeurs et les substitutions de commandes seront incluses dans le texte. Vous choisissez entre citer ou non la chaîne "EOF" selon que vous souhaitez ou non des substitutions.

Pour mettre les deux cat s dans le même fichier, nous utilisons la redirection >> pour la deuxième (et les suivantes) redirections : cela signifie ajouter au fichier. Pour le premier, nous utilisons un seul > pour effacer le fichier et recommencer à zéro.

Notez que, même lorsque des variables sont substituées, tout signe dollar supplémentaire dans la valeur de cette variable ne sont pas se sont re-substitués :

sans substituer la valeur de $bar.

Cependant, si vous fournissez un "$" dans l'argument de tout ce script, vous devez l'échapper sur la ligne de commande ou mettre le tout entre guillemets simples. Alternativement, la substitution de commandes, comme dans votre autre question, vous permet d'insérer directement le contenu d'un fichier entier, y compris les signes dollar dans le contenu du fichier. Assurez-vous de citer la chaîne de substitution ici :

obtiendra le corps de myfile en tant que $1 et pourra ensuite le catégoriser ou l'écho au besoin. Les mêmes limitations que dans ma réponse s'appliquent : il y a une limite pour la durée des arguments de ligne de commande, et si votre fichier peut être plus long que cela, vous devriez trouver une autre approche. Vous pouvez découvrir quelle est la limite sur votre système avec getconf ARG_MAX


Sortie de chaîne : imprimer/afficher une chaîne

La fonction printf standard est utilisée pour imprimer ou afficher des chaînes en C sur un périphérique de sortie. Le spécificateur de format utilisé est %s

La sortie de chaîne se fait avec les fonctions fputs() et printf().

Fonction fputs()

Le fputs() a besoin du nom de la chaîne et d'un pointeur vers l'endroit où vous souhaitez afficher le texte. Nous utilisons stdout qui fait référence à la sortie standard afin d'imprimer à l'écran. Par exemple :

Met la fonction

La fonction puts est utilisée pour imprimer une chaîne en C sur un périphérique de sortie et ramener le curseur à la première position. Une fonction puts peut être utilisée de la manière suivante,

La syntaxe de cette fonction est relativement simple que d'autres fonctions.


5 réponses 5

Vous ne pouvez pas développer les variables entre guillemets simples. Vous pouvez cependant terminer les guillemets simples et commencer les guillemets doubles :

Ou, vous pouvez inverser les guillemets doubles à l'intérieur des guillemets doubles :

Lorsque vous traitez l'impression de contenu variable, vous devez vous en tenir à printf au lieu de echo :

affichera visit: suivi du contenu de $site et d'une nouvelle ligne quels que soient les caractères de $site .

Si je comprends bien votre demande, vous pouvez évaluer la chaîne en écho. Par exemple.:

lors de la concaténation d'une chaîne et d'une variable, la variable doit être en dehors des guillemets car tout ce qui se trouve entre les guillemets sera imprimé littéralement.

Si vous vouliez continuer la chaîne après la variable, vous feriez de même :

Bien que s'il s'agissait d'une sorte d'énigme, je répondrais par ceci :

Comme le souligne Jander, cela est grand ouvert pour une attaque par injection. Ce n'était pas une réponse sérieuse, donc si quelqu'un envisageait d'utiliser quelque chose comme ça, ne l'utilisez pas avec une entrée non fiable. Par exemple, validez la chaîne $site comme étant une URL valide avant d'exécuter aveuglément le contenu. Quelque chose comme ça pourrait aider (mais l'expression fournie n'est pas parfaite car elle permet toujours l'injection, mais utilisez ce genre de mécanisme pour le tester).


1 réponse 1

Oui, c'est très certainement possible ! Pour ce faire, vous généreriez vos variables côté serveur de la même manière que vous le feriez en HTML - via des déclarations en ligne ou en utilisant Output() (AMPScript) ou Write() (SSJS).

Lors de l'utilisation SSJS vous pouvez utiliser la déclaration en ligne de <ctrl:var name="myVar" /> (voir mon article de blog ici pour des informations plus détaillées sur les capacités de this) pour pousser cette variable dans votre JS côté client existant.

L'autre option dans SSJS est d'écrire votre code JS côté client via un Write() . Cela l'aurait "codé en dur" dans la réponse donnée au navigateur demandeur.

Pour AMPScript, vous pouvez utiliser un déclaration en ligne de %%=v(@myVar)=%% pour pousser votre variable côté serveur dans JS côté client. Cela l'ajouterait dans un script existant écrit en dehors de votre code côté serveur.

Mais, si vous préférez gérer la construction de votre code au niveau du serveur via AMPScript, vous pouvez utiliser Output() combiné à un CONCAT() pour créer le même script qu'un Write() dans SSJS.

NOTE IMPORTANTE : Sachez que cela déplacera ces informations vers le « front-end » qui peut être lu par n'importe qui qui regarde le code source, donc aucune information privée ou sécurisée ne doit être transmise du côté serveur au côté client.


Voir la vidéo: Friday Night Flights: Lake Oswego High School 2019 season highlights