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?
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
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é.
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
où file2
est la liste de mots et file1
contient les phrases.
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("")
$> 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
.
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.
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.
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
). .
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