Wydrukuj słowo zawierające ciąg i pierwsze słowo

10

Chcę znaleźć ciąg w wierszu tekstu i wydrukować ciąg (między spacjami) i pierwsze słowo frazy.

Na przykład:

„To jest pojedyncza linia tekstu”
"Inna rzecz"
„Lepiej spróbuj ponownie”
"Lepszy"

Lista ciągów to:

tekst
rzecz
próbować
Lepszy

Próbuję uzyskać taki stół:

Ten [tab] tekst
Kolejna rzecz [tab]
To [tab] próbuje
Lepszy

Próbowałem z grepem, ale nic się nie wydarzyło. Jakieś sugestie?

Felipe Lira
źródło
Zatem w zasadzie „Jeśli linia ma ciąg, wypisz pierwsze słowo + ciąg”. Dobrze ?
Sergiy Kolodyazhnyy

Odpowiedzi:

12

Wersja 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

Nazwij to tak:

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

Wynik:

This    text
Another thing
It  try
Better
wjandrea
źródło
9

Perl na ratunek!

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

Zapisz jako first-plus-word, uruchom jako

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

Tworzy regex ze słów wejściowych. Każda linia jest następnie dopasowywana do wyrażenia regularnego, a jeśli występuje dopasowanie, drukowane jest pierwsze słowo, a jeśli jest inne niż słowo, słowo jest również drukowane.

choroba
źródło
9

Oto wersja 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

gdzie file2jest lista słów i file1zawiera wyrażenia.

steeldriver
źródło
2
Dobry! Umieściłem go w pliku skryptu, paste.ubuntu.com/23063130 , dla wygody
Sergiy Kolodyazhnyy
8

Oto wersja 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("")

Próbny:

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

Uwaga dodatkowa : skrypt jest python3zgodny, więc możesz go uruchomić za pomocą jednego python2lub dwóch python3.

Sergiy Kolodyazhnyy
źródło
7

Spróbuj tego:

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

Jeśli karta przed Betterznakiem stanowi problem, spróbuj wykonać następujące czynności:

$ 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

Powyższe zostało przetestowane na GNU sed (nazywane gsedna OSX). W przypadku BSD sed konieczne mogą być niewielkie zmiany.

Jak to działa

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

    To szuka słowa, [[:alnum:]]+po którym następuje spacja, [[:space:]]po którym następuje cokolwiek .*, po którym następuje jedno z twoich słów text|thing|try|Better, a po nim cokolwiek. Jeśli zostanie znaleziony, zostanie zastąpiony pierwszym słowem w linii (jeśli istnieje), tabulatorem i dopasowanym słowem.

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

    Jeśli polecenie podstawienia spowodowało podstawienie, co oznacza, że ​​jedno z twoich słów zostało znalezione w wierszu, to tapolecenie każe sedowi przejść do etykiety a. Jeśli nie, to rozgałęziamy ( b) do następnej linii. :aokreśla etykietę a. Tak więc, jeśli jedno z twoich słów zostało znalezione, my (a) dokonujemy podstawienia, s/^\t//które usuwa wiodącą kartę, jeśli istnieje, i (b) drukujemy ( p) wiersz.

John1024
źródło
7

Proste podejście 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

while read w; do ...; done < wordsBędzie iteracyjne nad każdą linię w pliku wordsi zapisać go jako $w. Te -nmarki sedniczego domyślnie nie drukuje. sedKomenda wtedy, zastąpi cudzysłowów stosowane przez nie-białych znaków ( \"(\S*), nawiasy służyć do „przechwytywania” co jest dopasowane \S*, pierwsze słowo, a my możemy później o nim jako o \1), 0 lub więcej znaków ( .*), a następnie szukane słowo ( $w) i ponownie 0 lub więcej znaków ( .*). Jeśli to pasuje, zastępujemy je tylko pierwszym słowem, tabulatorem i $w( \1\t$w), i wypisujemy wiersz (to właśnie robi pin s///p).

terdon
źródło
5

To jest wersja 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

Przykładowy plik tekstowy hello.txtzawiera

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

Uruchamianie z ruby source.rb hello.txtwynikami w

This    text
Another thing
It      try
Better
Anwar
źródło