J'essaie d'affiner mon code en supprimant les espaces blancs inutiles, les lignes vides et en équilibrant les parenthèses avec un espace entre elles, donc:
int a = 4;
if ((a==4) || (b==5))
a++ ;
devrait changer en:
int a = 4;
if ( (a==4) || (b==5) )
a++ ;
Cela fonctionne pour les crochets et les lignes vides. Cependant, il oublie de réduire les espaces multiples à un seul espace:
int a = 4;
if ( (a==4) || (b==5) )
a++ ;
Voici mon script:
#!/bin/bash
# Script to refine code
#
filename=read.txt
sed 's/((/( (/g' $filename > new.txt
mv new.txt $filename
sed 's/))/) )/g' $filename > new.txt
mv new.txt $filename
sed 's/ +/ /g' $filename > new.txt
mv new.txt $filename
sed '/^$/d' $filename > new.txt
mv new.txt $filename
Existe-t-il également un moyen de rendre ce script plus concis, par ex. supprimer ou réduire le nombre de commandes?
Si vous utilisez GNU sed alors vous devez utiliser sed -r
qui force sed
à utiliser des expressions régulières étendues, y compris le comportement souhaité de +
. Voir man sed
:
-r, --regexp-extended
use extended regular expressions in the script.
Il en va de même si vous utilisez OS X sed, mais vous devez alors utiliser sed -E
:
-E Interpret regular expressions as extended (modern) regular expressions
rather than basic regular regular expressions (BRE's).
Vous devez précéder +
avec un \
, sinon sed
essaie de faire correspondre le caractère +
lui-même.
Pour rendre le script "plus intelligent", vous pouvez accumuler toutes les expressions dans un sed:
sed -e 's/((/( (/g' -e 's/))/) )/g' -e 's/ \+/ /g' -e '/^$/d' $filename > new.txt
Certaines implémentations de sed
prennent même en charge le -i
option qui permet de changer le fichier en place.
Parfois, -r et -e ne fonctionneront pas. J'utilise la version 4.2.1 de sed et ils ne fonctionnent pas du tout pour moi.
Un hack rapide consiste à utiliser l'opérateur * à la place. Disons donc que nous voulons remplacer tous les caractères d'espace redondants par un seul espace: Nous aimerions faire:
sed 's/ +/ /'
Mais nous pouvons utiliser ceci à la place:
sed 's/ */ /'
(notez le double espace)
Ce n'est peut-être pas la solution la plus propre. Mais si vous voulez éviter -E
et -r
pour rester compatible avec les deux versions de sed, vous pouvez répéter le caractère cc*
- c'est 1 c
puis 0 ou plus c
's ==
1 ou plusieurs c
.
Ou utilisez simplement la syntaxe BRE, comme suggéré par @ cdarke , pour faire correspondre un nombre ou des modèles spécifiquesc\{1,\}
. Le deuxième nombre après la virgule est exclu pour signifier 1 ou plus.
sur le front bash;
J'ai d'abord fait un script test.sh
cat test.sh
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
SRC=`echo $line | awk '{print $1}'`
DEST=`echo $line | awk '{print $2}'`
echo "moving $SRC to $DEST"
mv $SRC $DEST || echo "move $SRC to $DEST failed" && exit 1
done < "$1"
puis on fait un fichier de données et un fichier de test aaa.txt
cat aaa.txt
<tag1>19</tag1>
<tag2>2</tag2>
<tag3>-12</tag3>
<tag4>37</tag4>
<tag5>-41</tag5>
puis testez et affichez les résultats.
bash test.sh list.txt
Text read from file: aaa.txt bbb.txt
moving aaa.txt to bbb.txt
Cela pourrait fonctionner pour vous:
sed -e '/^$/d' -e ':a' -e 's/\([()]\)\1/\1 \1/g' -e 'ta' -e 's/ */ /g' $filename >new.txt