web-dev-qa-db-fra.com

Imprimer Word contenant la chaîne et le premier mot

Je veux trouver une chaîne dans une ligne de texte et imprimer la chaîne (entre les espaces) et le premier mot de la phrase.

Par exemple:

 "Ceci est une seule ligne de texte" 
 "Une autre chose" 
 "Il vaut mieux réessayer" 
 "Mieux" 

La liste des chaînes est:

 texte 
 chose 
 essayer 
 Mieux 

Ce que j'essaie, c'est d'obtenir un tableau comme celui-ci:

 Cet [onglet] texte 
 Une autre [onglet] chose 
 Il [onglet] essayer 
 Mieux 

J'ai essayé avec grep mais rien ne s'est passé. Toute suggestion?

9
Felipe Lira

Version Bash/grep:

#!/bin/bash
# string-and-first-Word.sh
# Finds a string and the first Word of the line that contains that string.

text_file="$1"
shift

for string; do
    # Find string in file. Process output one line at a time.
    grep "$string" "$text_file" | 
        while read -r line
    do
        # Get the first Word of the line.
        first_Word="${line%% *}"
        # Remove special characters from the first Word.
        first_Word="${first_Word//[^[:alnum:]]/}"

        # If the first Word is the same as the string, don't print it twice.
        if [[ "$string" != "$first_Word" ]]; then
            echo -ne "$first_Word\t"
        fi

        echo "$string"
    done
done

Appelez ça comme ça:

./string-and-first-Word.sh /path/to/file text thing try Better

Sortie:

This    text
Another thing
It  try
Better
12
wjandrea

Perl à la rescousse!

#!/usr/bin/Perl
use warnings;
use strict;

my $file = shift;
my $regex = join '|', map quotemeta, @ARGV;
$regex = qr/\b($regex)\b/;

open my $IN, '<', $file or die "$file: $!";
while (<$IN>) {
    if (my ($match) = /$regex/) {
        print my ($first) = /^\S+/g;
        if ($match ne $first) {
            print "\t$match";
        }
        print "\n";
    }
}

Enregistrer sous first-plus-Word, exécuté sous

Perl first-plus-Word file.txt text thing try Better

Il crée une expression rationnelle à partir des mots entrés. Chaque ligne est ensuite comparée à l'expression régulière, et s'il y a correspondance, le premier mot est imprimé, et s'il est différent du mot, le mot est également imprimé.

9
choroba

Voici une version awk:

awk '
  NR==FNR {a[$0]++; next;} 
  {
    gsub(/"/,"",$0);
    for (i=1; i<=NF; i++)
      if ($i in a) printf "%s\n", i==1? $i : $1"\t"$i;
  }
  ' file2 file1

file2 est la liste de mots et file1 contient les phrases.

9
steeldriver

Voici la version python:

#!/usr/bin/env python
from __future__ import print_function 
import sys

# List of strings that you want
# to search in the file. Change it
# as you fit necessary. Remember commas
strings = [
          'text', 'thing',
          'try', 'Better'
          ]


with open(sys.argv[1]) as input_file:
    for line in input_file:
        for string in strings:
            if string in line:
               words = line.strip().split()
               print(words[0],end="")
               if len(words) > 1:
                   print("\t",string)
               else:
                   print("")

Démo:

$> cat input_file.txt                                                          
This is a single text line
Another thing
It is better you try again
Better
$> python ./initial_Word.py input_file.txt                                      
This    text
Another     thing
It  try
Better

note latérale: Le script est compatible python3, vous pouvez donc l'exécuter avec python2 ou python3.

8
Sergiy Kolodyazhnyy

Essaye ça:

$ sed -En 's/(([[:alnum:]]+)[[:space:]].*)?(text|thing|try|Better).*/\2\t\3/p' File
This    text
Another thing
It      try
        Better

Si l'onglet précédant la Better pose un problème, essayez ceci:

$ sed -En 's/(([[:alnum:]]+)[[:space:]].*)?(text|thing|try|Better).*/\2\t\3/; ta; b; :a; s/^\t//; p' File
This    text
Another thing
It      try
Better

Ce qui précède a été testé sur GNU sed (appelé gsed sur OSX). Pour BSD sed, des modifications mineures peuvent être nécessaires.

Comment ça fonctionne

  • s/(([[:alnum:]]+)[[:space:]].*)?(text|thing|try|Better).*/\2\t\3/

    Cela recherche un mot, [[:alnum:]]+, suivi d'un espace, [[:space:]], suivi de rien, .*, suivi de l'un de vos mots, text|thing|try|Better, suivi de rien. Si cela est trouvé, il est remplacé par le premier mot de la ligne (le cas échéant), un onglet et le mot correspondant.

  • ta; b; :a; s/^\t//; p

    Si la commande de substitution a entraîné une substitution, ce qui signifie qu'un de vos mots a été trouvé sur la ligne, la commande ta indique à sed de passer à l'étiquette a. Si ce n'est pas le cas, on passe à la ligne suivante (b). :a définit l'étiquette a. Donc, si l’un de vos mots est trouvé, nous (a) faisons la substitution s/^\t// qui supprime un onglet principal s’il en existe un, et (b) affiche (p) la ligne.

7
John1024

Une approche simple bash/sed:

$ while read w; do sed -nE "s/\"(\S*).*$w.*/\1\t$w/p" file; done < words 
This    text
Another thing
It  try
    Better

Le while read w; do ...; done < words va parcourir chaque ligne du fichier words et l'enregistrer en tant que $w. Le -n permet à sed de ne rien imprimer par défaut. La commande sed remplacera alors les guillemets doubles suivis par des non-espaces (\"(\S*), les parenthèses servent à "capturer" ce que correspond à \S*, le premier mot, et nous pourrons plus tard appelez-le \1), 0 ou plusieurs caractères (.*), puis le mot que nous recherchons ($w) et encore 0 ou plusieurs caractères (.* ). Si cela correspond, nous le remplaçons uniquement par le premier mot, un onglet et $w (\1\t$w), puis imprimons la ligne (c'est ce que fait la p dans s///p). .

7
terdon

Ceci est la version Ruby

str_list = ['text', 'thing', 'try', 'Better']

File.open(ARGV[0]) do |f|
  lines = f.readlines
  lines.each_with_index do |l, idx|
    if l.match(str_list[idx])
      l = l.split(' ')
      if l.length == 1
        puts l[0]
      else
        puts l[0] + "\t" + str_list[idx]
      end
    end
  end
end

Le fichier texte d'exemple hello.txt contient

This is a single text line
Another thing
It is better you try again
Better

Courir avec Ruby source.rb hello.txt a pour résultat

This    text
Another thing
It      try
Better
5
Anwar