En utilisant le symbole "*" ((il n’est pas nécessaire que ce soit celui-ci, aucun caractère spécial ne le fera pour indiquer)), comment puis-je modifier le texte à partir de ceci:
*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*
Pour ça:
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Chaque caractère après le premier astérisque correspondant sera placé sur chaque ligne jusqu'à ce que le deuxième astérisque soit trouvé.
Des pistes sur comment je peux m'y prendre? (sed ou awk serait préféré, mais si vous pouvez penser à une autre façon, s'il vous plaît envoyez-moi votre code!)
Je sais comment supprimer toutes les lignes contenant un astérisque, c'est juste la partie de placement de personnage à laquelle je ne peux pas penser
Ce code awk
pourrait suffire:
awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'
Pour le décomposer:
*
comme séparateur de champ. De cette façon, nous pouvons simplement examiner le nombre de champs (NF
) pour déterminer si le début ou la fin d'un bloc est atteint.label
et continuons à la ligne suivante.label
à la ligne en cours, puis imprimons. Si l'étiquette est vide, nous sommes en dehors d'un bloc et il n'y a aucun effet. Sinon, nous obtenons la sortie requise.Dans sed
, vous pouvez copier la ligne "spéciale" dans l'espace réservé avant de la supprimer.
sed -e '/^\*/{h;d;}'
puis ajoutez l'espace de maintien à chaque espace de motif suivant, en remplaçant le caractère de nouvelle ligne et de marqueur résultant
-e '{G;s/\n\*//;}'
Le tester avec vos données,
$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Note: cela ne s'arrête pas quand il rencontre le deuxième astérisque; il fait exactement la même chose, mais ajoute *
suivi de rien - jusqu'à ce qu'il corresponde au prochain *sometext
.
Voici un moyen Perl:
_$ Perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
_
Le _-n
_ amènera Perl à lire chaque ligne du fichier d'entrée, en l'enregistrant dans la variable spéciale _$_
_, le _-l
_ le fera: i) éliminer les nouvelles lignes (_\n
_) de chaque ligne et ii) ajouter une nouvelle ligne à chaque appel de print
. _-e
_ est le script qui est appliqué à chaque ligne.
/^\*(.*)/
: associe les lignes commençant par un astérisque et enregistre tout ce qui suit après l'astérisque sous le nom _$1
_ (c'est ce que font les parenthèses).
_|| print "$_$1"'
_: le _||
_ est un OR
logique. Par conséquent, la print
ne sera exécutée que si la ligne en cours ne commence pas par un astérisque. Si c'est le cas, nous imprimons la ligne en cours (_$_
_) ainsi que tout ce qui est actuellement enregistré sous le nom _$1
_ (le motif qui suit l'astérisque).
Comme d'habitude, il y a plusieurs façons de le faire. Une solution stupide et inefficace, mais qui met en évidence les capacités de manipulation de chaînes du shell, est la suivante:
_$ while read line; do
[[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat";
done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
_
while read line; do ... ; done < file
_: il s'agit d'une boucle classique while
qui lit chaque ligne du fichier d'entrée file
et l'enregistre sous le nom _$line
_.[[ $line =~ ^\* ]] && pat="${line#\*}"
_: si la ligne commence par un _*
_, supprimez tout ce qui suit (c'est ce que fait le _${line#\*}
_, pour plus de détails, voir ici ) et enregistrez-le comme _$pat
_. * _|| printf "%s%s\n" "$line" "$pat";
_: si la commande précédente a échoué (la ligne ne commence donc pas par un astérisque), imprimez la ligne et la valeur actuelle de _$pat
_.À travers mon Python préféré ...
with open('/path/to/the/file') as f:
counter = False
for line in f:
if line.startswith('*') and not counter:
m = line.strip().lstrip('*')
counter = True
Elif line.startswith('*') and counter:
counter = False
Elif counter:
if not line.startswith('*'):
print(line.strip() + m)
else:
print(line.strip())
Je suis arrivé tard. Voici une autre approche python
:
#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
for lines in f.read().split('*'):
entries = lines.rstrip().split('\n')
for i in range(1, len(entries)):
print entries[i] + entries[0]