Imprimir palabra que contiene cadena y primera palabra


10

Quiero encontrar una cadena en una línea de texto e imprimir la cadena (entre espacios) y la primera palabra de la frase.

Por ejemplo:

"Esta es una sola línea de texto"
"Otra cosa"
"Es mejor que lo intentes de nuevo"
"Mejor"

La lista de cadenas es:

texto
cosa
tratar
Mejor

Lo que intento es obtener una tabla como esta:

Este texto [tab]
Otra cosa [tab]
[Tab] intente
Mejor

Lo intenté con grep pero no ocurrió nada. ¿Cualquier sugerencia?


Entonces, básicamente "Si la línea tiene cadena, imprime la primera palabra + cadena". Derecho ?
Sergiy Kolodyazhnyy

Respuestas:


12

Versión 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

Llámalo así:

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

Salida:

This    text
Another thing
It  try
Better

9

¡Perl al rescate!

#!/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";
    }
}

Guardar como first-plus-word, correr como

perl first-plus-word file.txt text thing try Better

Crea una expresión regular de las palabras de entrada. Cada línea se compara con la expresión regular, y si hay una coincidencia, se imprime la primera palabra, y si es diferente a la palabra, la palabra también se imprime.


9

Aquí hay una versión 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

donde file2está la lista de palabras y file1contiene las frases.


2
Bueno uno! Lo puse en un archivo de script, paste.ubuntu.com/23063130 , solo por conveniencia
Sergiy Kolodyazhnyy

8

Aquí está la versión de 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("")

Manifestación:

$> 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

Nota al margen : el script es python3compatible, por lo que puede ejecutarlo con python2o python3.


7

Prueba esto:

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

Si la pestaña anterior Betteres un problema, intente esto:

$ 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

Lo anterior se probó en GNU sed (llamado gseden OSX). Para BSD sed, pueden ser necesarios algunos cambios menores.

Cómo funciona

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

    Esto busca una palabra, [[:alnum:]]+seguida de un espacio, [[:space:]]seguida de cualquier cosa .*, seguida de una de sus palabras text|thing|try|Better, seguida de cualquier cosa. Si se encuentra eso, se reemplaza con la primera palabra en la línea (si existe), una pestaña y la palabra coincidente.

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

    Si el comando de sustitución resultó en una sustitución, lo que significa que una de sus palabras se encontró en la línea, entonces el tacomando le dice a sed que salte a la etiqueta a. Si no, entonces ramificamos ( b) a la siguiente línea. :adefine la etiqueta a. Entonces, si se encontró una de sus palabras, nosotros (a) hacemos la sustitución s/^\t//que elimina una pestaña inicial si hay una, y (b) imprimimos ( p) la línea.


7

Un enfoque 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

El while read w; do ...; done < wordsiterará sobre cada línea en el archivo wordsy lo guardará como $w. Las -nmarcas sedno imprimen nada por defecto. El sedcomando a continuación, reemplazará a las comillas dobles seguidos de no está en blanco ( \"(\S*)los paréntesis sirven para "capturar" lo que se corresponde con \S*la primera palabra, y después nos pueden referirse a ella como \1), 0 o más caracteres ( .*) y luego el palabra que estamos buscando ( $w) y 0 o más caracteres nuevamente ( .*). Si esto coincide, lo reemplazamos con solo la primera palabra, una pestaña y $w( \1\t$w), e imprimimos la línea (eso es lo que hace el pin s///p).


5

Esta es la versión 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

El archivo de texto de muestra hello.txtcontiene

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

Ejecutando con ruby source.rb hello.txtresultados en

This    text
Another thing
It      try
Better
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.