1
votes

Comment permuter deux chaînes à l'aide de la commande sed avec le délimiteur étant une virgule?

c'est la première fois que je poste ici, alors je m'excuse si le formatage est tout à fait bizarre.

En utilisant la commande sed, je veux permuter x et y, de x, y en y, x et stocker la version permutée dans un fichier séparé.

Le fichier que je suis censé modifier contient,

#######bank info########
#
####name####    ####age####
#
Bob,Stevenson       27
David,Tan           43
Robert,Jackson      39

Je veux changer le nom de prénom, nom en nom, prénom.

J'ai déjà essayé d'utiliser la commande,

#######bank info########
#
####name####    ####age####
#
Stevenson,Bob       27
Tan,David           43
Jackson,Robert      39

Pourtant, quand j'examine le fichier "swappé", il semble que rien n'a changé. Pourquoi?

Le résultat attendu est:

sed -e "s/^\([^#]*\) *\([,]*\)/\2\1/g" file > xxx

Mais mon résultat est:

#######bank info########
#
####name####    ####age####
#
Bob,Stevenson       27
David,Tan           43
Robert,Jackson      39

Lequel est exactement la même que la version initiale. Pourquoi cela se produit-il?


2 commentaires

Est-ce que cela répond à votre question? permuter les colonnes à l'aide de sed


@oguz ismail Merci pour la réponse! Je ne sais pas comment fonctionne le code qu'ils ont fourni. sed 's / ([^:] *:) ([^] *) ([^:] *) / \ 1 \ 3 \ 2 /' test. Pourquoi ont-ils 3 de ((...))?


3 Réponses :


0
votes
sed '/^#/!s/^\([^,]*\),\([^ ]*\)/\2,\1/'

2 commentaires

Merci beaucoup! Je vois ce que j'ai fait de mal. Je pensais que ([^ #] *) signifiait correspondre à tout le reste, sauf ceux qui commencent par # car utiliser ^ dans un caractère générique ne signifiait pas ce qu'il suit.


Bien sûr, mais aussi le [^ #] * correspondra à tout jusqu'à ce que le # , mais le * correspond à zéro ou plusieurs caractères. Il peut donc correspondre à zéro caractères en fait. Je pense que vous pouvez également s / ^ \ ([^ #,] \ + \), \ ([^] * \) / \ 2, \ 1 / , mais je me sentais comme / ^ # /! est plus explicite que nous voulons ignorer les commentaires. Parce que c'est plus facile ex. à / ^ [\ t] * # /! pour ignorer également les commentaires qui sur les lignes commençant par un espace ou des tabulations suivis de # .



0
votes

Même approche que la très bonne réponse de @KamilCuk, mais en utilisant des expressions régulières et des mots, vous pouvez faire

$ sed -E '/,/s/(\w+),(\w+)/\2,\1/' file
#######bank info########
#
####name####    ####age####
#
Stevenson,Bob       27
Tan,David           43
Jackson,Robert      39

/, / ne fonctionne que sur les lignes avec un ',' et les groupes de capture de (\ w +) correspondent à des groupes d'un ou plusieurs mots-caractères. L'expression (\ w +), (\ w +) garantit qu'il y a deux groupes de mots-caractères séparés par une virgule, puis le \ 2, \ 1 réinsère simplement le références arrière dans l'ordre inverse, par exemple

Exemple d'utilisation / sortie

sed -E '/,/s/(\w+),(\w+)/\2,\1/' file > newfile


2 commentaires

Ahhh cela a tellement de sens! Je n'ai pas encore entendu parler de (\ w +), donc c'est très utile. Merci beaucoup!


Oui, et toutes les subtilités des expressions régulières étendues aident à résoudre très bien certains des problèmes liés aux mots et aux limites de mots - mais les expressions régulières étendues ne sont pas disponibles pour tous les sed , il vaut donc mieux le savoir comment utiliser les deux :)



0
votes

Si vous pouvez utiliser awk , cela fera l'affaire.

awk -F'[ ,]+' '/,/{$0=$2","$1"\t"$3}1' file
#######bank info########
#
####name####    ####age####
#
Stevenson,Bob   27
Tan,David       43
Jackson,Robert  39

Il peut être plus facile de comprendre le awk par rapport à sed :)

  • -F '[] +' Diviser la ligne par une ou plusieurs virgules ou espaces
  • /, / pour les lignes avec virgule faire:
  • $ 0 = $ 2 "," $ 1 "\ t" $ 3 reconstruire la ligne dans un nouvel ordre avec une virgule et une tabulation
  • 1 toujours vrai, effectuez l'action par défaut, imprimez la ligne.


0 commentaires