2017-10-14 3 views
2

J'ai lu cet article: sed delete remaining characters in line except first 5 qui m'aide à supprimer tous les caractères après x. Cependant, j'ai du mal à trouver comment supprimer tous les mots après x caractères.Comment faire pour supprimer tous les mots après X caractères

J'ai commencé avec ce code:

echo "StackOverflow Users Are Brilliant And Hard Working" | sed 's/.//30g' 
#character 30 ---------------------^ 

Ma tentative:

echo "StackOverflow Users Are Brilliant And Hard Working" | sed 's/ .* //30g' 
#character 30 ---------------------^ 

Dans ces sorties, je soit coupé le dernier mot ou le comptage des mots. Au lieu de cela, je dois supprimer les mots après 30 caractères. Je cours cela sur différentes longueurs de lignes/mots, c'est pourquoi je ne peux pas simplement le mettre à la fin du mot.

sortie souhaitée:

StackOverflow Users Are Brilliant 

Si vous savez comment mettre en comptant ensemble les mots après x caractères, votre aide serait grandement appréciée.

Veuillez noter: Comme indiqué précédemment, ne modifiez pas le code en 33 ou 34 caractères. Le point de la question est de supprimer tous les mots après 30 caractères.

Répondre

2

Ce awk sera faire

$ awk 'BEGIN{FS=OFS="" } length>30{i=30; while($i~/\w/) i++; NF=i-1; }1' file 
StackOverflow Users Are Brilliant 
This line has 22 chars 

Réglage FS=OFS="" de sorte que chaque charbon est considéré comme un champ

Si length>30 puis i=30; while($i~/\w/) i++; i.e. garder incrémenter i jusqu'à ce que nous atterrissons à caractère non alnum; Une fois la boucle terminée, définissez le NF souhaité.

La ligne avec length<=30 sera imprimée telle quelle.

En utilisant grep

$ grep -oE "^.{1,29}\w*" file 
StackOverflow Users Are Brilliant 
This line has 22 chars 

^.{1,29}\w*: 1-29 parce que si 30th caractère est non alnum alors il ne doit pas être considéré.

+1

Cool solution @batman :-) Fonctionne pour moi! – DomainsFeatured

+0

Grep solution est la plus courte, j'essayais de résoudre cela avec grep aussi, mais j'ai oublié '^' et il a produit plusieurs lignes. –

+0

@ PawełTatarczuk @batMan, j'ai effectivement utilisé la solution de Pawel dans mon programme. Mais, j'ai choisi cela à cause de la double réponse de 'awk' et' grep'. En outre, il a le meilleur score et je vous dois un batman. Pawel, j'espère que beaucoup de gens ont voté pour votre réponse parce que vous avez donné une explication très utile. Cela m'a beaucoup aidé et aidera les autres aussi. Merci encore batMan :-) – DomainsFeatured

2

Que diriez-vous awk simple et sobre avec son utilitaire substr magique:

echo "StackOverflow Users Are Brilliant And Hard Working" | awk '{print substr($0,1,34)}' 

Si vous voulez passer la longueur à awk puis en suivant peut vous aider dans la même.

echo "StackOverflow Users Are Brilliant And Hard Working" | awk -v end=34 '{print substr($0,1,end)}' 

Si vous voulez avoir votre longueur sauf dans une variable shell et que vous souhaitez passer à awk puis en suivant peut vous aider dans la même.

val="34" 
echo "StackOverflow Users Are Brilliant And Hard Working" | awk -v var="$val" '{print substr($0,1,var)}' 

EDIT: Ajout d'une solution sed sur la même trop.

echo "StackOverflow Users Are Brilliant And Hard Working" | sed 's/\(.\{34\}\)\(.*\)/\1/' 
+1

@DomainsFeatured, votre accueil. Voir mon EDIT ajouté 3 autres moyens (y compris sed) pour résoudre ce problème, laissez-moi savoir si des requêtes sur le même. – RavinderSingh13

+1

Oh merde, je viens de réaliser que ça ne marche pas! Je ai besoin de travailler sur 30 caractères, pas 34 :-(La sortie est: 'StackOverflow utilisateurs sont Brilli' – DomainsFeatured

+0

@DomainsFeatured, j'avais donné cette solution de 34 caractères parce que j'ai vu votre sortie attendue (qui était là jusqu'au mot Brilliant) , évidemment, vous pouvez ajuster les caractères selon vos besoins. – RavinderSingh13

1

Vous pouvez le faire avec sed:

echo "StackOverflow Users Are Brilliant And Hard Working" | sed 's/\(.\{1,30\}\w*\)\(.*\)/\1/' 

Cela devrait fonctionner pour le texte moins de 30 caractères et - pas parage se passe dans ce cas.

Explication

C'est le regex j'ai commencé avec:

.{1,30}\w* 

Il obtient simplement 1-30 caractères, puis tous les caractères de mots supplémentaires qui sont juste après.

maintenant pour pouvoir l'utiliser dans sed nous avons dû dépouiller tout le reste nous avons besoin de deux groupes:

(.{1,30}\w*)(.*) 

Aujourd'hui, certains s'échappent pour «() » et « {} »:

\(.\{1,30\}\w*\)\(.*\) 

Cela peut aller à sed:

sed 's/<pattern>/<replacement>/<flags>' 

nous voulons supprimer deuxième groupe, alors que le remplacement en sed nous utilisons \ '1' (premier groupe):

echo "..." | sed 's/\(.\{1,30\}\w*\)\(.*\)/\1/' 
+0

Hey Pawel, oui! C'est ce que je cherchais. Si vous pouviez fournir une explication pour la partie '\ (. \ {1,30 \} \ w \ + \) \ (. * \)/\ 1', j'aimerais apprendre. Sinon, merci pour l'aide. Je vais marquer la meilleure réponse plus tard aujourd'hui :-) – DomainsFeatured

+0

Il y avait erreur mineure, j'ai édité la réponse. Je vais écrire une explication en quelques minutes. –

+1

Explication ajoutée –

1

Cela pourrait fonctionner pour vous (GNU sed):

sed -r 's/^(.{30}\S*).*/\1/' file 

Ce conserve les 30 premiers caractères et les caractères suivants non-espace.

N.B. si le caractère 30 est un espace, le mot suivant sera inclus, de sorte que le regexp pourrait être:

sed -r 's/^(.{29}\S*).*/\1/' file 
+0

Hey @potong, merci pour la réponse et l'explication génial. Cela fait beaucoup de sens :-) – DomainsFeatured

1

Avec bash

var="StackOverflow Users Are Brilliant And Hard Working" 
echo ${var:0:30} 

Ou

expr substr "$var" 1 30 
+0

Ne fonctionne pas pour moi ... Je reçois la sortie: «Utilisateurs StackOverflow sont Brilli» – DomainsFeatured

+0

désolé, je comprends que vous voulez arrêter après 30 char –

+0

oui, mais je dois inclure le reste de le mot 'StackOverflow Users are Brilliant'. Votre sortie coupe 'Brilliant' en' Brilli' – DomainsFeatured

0

Avec awk GNU gensub():

$ awk '{$0=gensub(/(.{30}\S*).*/,"\\1",1)} 1' file 
StackOverflow Users Are Brilliant 

ou GNU sed:

$ sed -E 's/(.{30}\S*).*/\1/' file 
StackOverflow Users Are Brilliant