1
votes

AWK ne met pas à jour l'enregistrement avec un nouveau séparateur

Je suis un peu confus avec awk (je suis totalement nouveau dans awk)

find static/* | awk -F/ '{$1="";OFS="#";print $(0)}'
 conf
^ a space and no / ?
#conf#server.xml

mon objectif est de supprimer 'static /' du résultat Première étape:

conf
conf/server.xml

Même résultat. Je m'y attendais. Suppression maintenant de la première partie:

find static/* | awk -F/ '{$1="";OFS=FS;print $(0)}'
 conf
/conf/server.xml

c'est presque bien, mais je ne sais pas pourquoi le délimiteur est tué Mais je peux m'en occuper en ajoutant simplement le délimiteur à la sortie:

 find static/* | awk -F/ '{$1="";print $(0)}'
 conf
 conf server.xml

OK maintenant je suis complètement perdu. Pourquoi un «/» est-il sur la deuxième ligne et non sur la première? Dans les deux cas, j'ai supprimé la première colonne.

Des explications, des idées. BTW ma sortie préférée serait

find static/* | awk -F/ '{print $(0)}'
static/conf
static/conf/server.xml

Addendum: merci pour vos aimables réponses. ils m'aideront à résoudre le problème. Cependant, je veux comprendre pourquoi le premier «/» est supprimé lors de mon dernier essai. Pour rendre les choses un peu plus claires:

find static/*

static/conf
static/conf/server.xml

awk

0 commentaires

4 Réponses :


1
votes

1ère solution: Considérant que dans votre sortie le mot statique ne viendra qu'une fois si c'est le cas, essayez. Je crée simplement un séparateur de champ sous forme de chaîne static / pour les lignes et j'imprime le dernier champ de lignes alors qui sera après le mot static / .

find static/* | awk 'match($0,/\/.*/){print substr($0,RSTART+1,RLENGTH)}'


2ème solution: Ajout d'une solution plus générique ici. Ce qui correspondra aux valeurs de la toute première occurrence de / au dernier de la ligne et lors de l'impression, il ne sera pas imprimé à partir de / .

find static/* | awk -F'static/' '{print $NF}'


0 commentaires

0
votes

Lorsque vous réinitialisez la première valeur de champ, le champ est toujours là. Supprimez simplement les caractères / initiaux après cela avec sub (/ ^ \ / + /, "") (où le motif ^ \ / + correspond un ou plusieurs caractères / au début de la chaîne):

conf
conf/server.xml

Voir un démo en ligne :

s="static/conf
static/conf/server.xml"
awk 'BEGIN{OFS=FS="/"} {$1="";sub(/^\/+/, "")}1' <<< "$s"

Sortie:

awk 'BEGIN{OFS=FS="/"} {$1="";sub(/^\/+/, "")}1'

Notez qu'avec BEGIN {OFS = FS = "/"} vous définissez le séparateur de champ d'entrée / sortie une seule fois au début, et 1 à la fin déclenche l'opération d'impression de ligne par défaut. P >


0 commentaires

2
votes

Si vous avez GNU, trouvez que vous n'avez pas du tout besoin de awk.

$ find static/ -mindepth 1 -printf '%P\n'
conf
conf/server.xml


0 commentaires

2
votes

mais je ne sais pas pourquoi le délimiteur est supprimé.

Chaque fois que vous redéfinissez un champ dans awk en utilisant une instruction comme:

awk 'BEGIN{FS=OFS="/"}{$1=""}{print substr($0,2)}'

awk reconstruira l'enregistrement actuel $ 0 et remplacera automatiquement tous les séparateurs de champ défini par FS , par le séparateur de champ de sortie OFS (voir ci-dessous). La valeur par défaut de OFS est un espace unique. Cela implique ce qui suit:

  • awk -F / '{$ 1 = ""; print $ (0)}'

    Le séparateur de champ FS est défini sur un seul caractère . Le premier champ est remis à "" ce qui permet la réévaluation de $ 0 par laquelle toutes les correspondances d'expressions régulières correspondant à FS sont remplacées par le chaîne OFS qui est actuellement un seul espace.

  • awk -F / '{$ 1 = ""; OFS = FS; print $ (0)'

    La même action s'applique que précédemment. Cependant, après le recalcul de $ 0 , le séparateur de champ de sortie OFS est mis à FS . Cela implique qu'à partir de l'enregistrement 2, vous ne remplacerez pas FS par un espace, mais par la valeur de FS .

Solution possible avec la même idéologie

$n = new_value

La fonction de sous-chaîne substr est nécessaire pour supprimer le premier /


L'utilitaire awk doit interpréter chaque enregistrement d'entrée comme une séquence de champs où, par défaut, un champ est une chaîne de caractères non- non-. Ce séparateur de champ par défaut et peut être modifié à l'aide de la variable intégrée FS ou de l'option sepstring -F . L'utilitaire awk doit désigner le premier champ d'un enregistrement $ 1 , le deuxième $ 2 , et ainsi de suite. Le symbole $ 0 fera référence à l'ensemble de l'enregistrement; la définition de tout autre champ entraîne la réévaluation de $0 . L'affectation à $ 0 réinitialisera les valeurs de tous les autres champs et de la variable intégrée NF .

Variables et variables spéciales

Les références à des champs inexistants (c'est-à-dire des champs après $ NF ), doivent être évalués à la valeur non initialisée. Ces références ne doivent pas créer de nouveaux champs. Cependant, l'assignation à un champ inexistant (par exemple, $ (NF + 2) = 5 ) augmentera la valeur de NF ; créer tous les champs intermédiaires avec la valeur non initialisée; et faire recalculer la valeur de $ 0 , les champs étant séparés par la valeur de OFS . Chaque variable de champ doit avoir une valeur de chaîne ou une valeur non initialisée lors de sa création. Les variables de champ doivent avoir la valeur non initialisée lorsqu'elles sont créées à partir de $ 0 en utilisant FS et la variable ne contient aucun caractère.

source: Norme POSIX: utilitaire awk a>

Sachez que le séparateur de champ par défaut FS = "" a des règles spéciales


1 commentaires

Merci beaucoup! Cela aide à comprendre le comportement.1