Druckwort mit Zeichenfolge und erstem Wort

10

Ich möchte eine Zeichenfolge in einer Textzeile finden und die Zeichenfolge (zwischen Leerzeichen) und das erste Wort der Phrase drucken.

Beispielsweise:

"Dies ist eine einzelne Textzeile"
"Etwas anderes"
"Es ist besser, du versuchst es noch einmal."
"Besser"

Die Liste der Zeichenfolgen lautet:

Text
Sache
Versuchen
Besser

Ich versuche, eine Tabelle wie diese zu erhalten:

Dieser [Tab] Text
Eine andere Sache
Es [tab] versuchen
Besser

Ich habe es mit grep versucht, aber es ist nichts passiert. Irgendein Vorschlag?

Felipe Lira
quelle
Also im Grunde "Wenn die Zeile eine Zeichenfolge hat, drucke das erste Wort + die Zeichenfolge". Richtig ?
Sergiy Kolodyazhnyy

Antworten:

12

Bash / Grep-Version:

#!/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

Nennen Sie es so:

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

Ausgabe:

This    text
Another thing
It  try
Better
wjandrea
quelle
9

Perl zur Rettung!

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

Speichern unter first-plus-word, ausführen als

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

Aus den eingegebenen Wörtern wird ein regulärer Ausdruck erstellt. Jede Zeile wird dann mit dem regulären Ausdruck abgeglichen. Wenn eine Übereinstimmung vorliegt, wird das erste Wort gedruckt, und wenn es sich vom Wort unterscheidet, wird auch das Wort gedruckt.

Choroba
quelle
9

Hier ist eine awk-Version:

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

Wo file2ist die Wortliste und file1enthält die Sätze.

Steeldriver
quelle
2
Gut! Ich habe es in eine Skriptdatei eingefügt , paste.ubuntu.com/23063130 , nur der
Einfachheit halber
8

Hier ist die Python-Version:

#!/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("")

Demo:

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

Randnotiz : Das Skript ist python3kompatibel, sodass Sie es entweder mit python2oder ausführen können python3.

Sergiy Kolodyazhnyy
quelle
7

Versuche dies:

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

Wenn die Registerkarte vor dem Betterein Problem darstellt, versuchen Sie Folgendes:

$ 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

Das Obige wurde auf GNU sed ( gsedunter OSX aufgerufen ) getestet . Für BSD sed sind möglicherweise einige geringfügige Änderungen erforderlich.

Wie es funktioniert

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

    Dies sucht nach einem Wort, [[:alnum:]]+gefolgt von einem Leerzeichen, [[:space:]]gefolgt von irgendetwas .*, gefolgt von einem Ihrer Wörter text|thing|try|Better, gefolgt von irgendetwas. Wenn dies gefunden wird, wird es durch das erste Wort in der Zeile (falls vorhanden), eine Registerkarte und das übereinstimmende Wort ersetzt.

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

    Wenn der Substitutionsbefehl zu einer Substitution führte, was bedeutet, dass eines Ihrer Wörter in der Zeile gefunden wurde, weist der taBefehl sed an, zum Label zu springen a. Wenn nicht, verzweigen wir ( b) in die nächste Zeile. :adefiniert die Bezeichnung a. Wenn also eines Ihrer Wörter gefunden wurde, führen wir (a) die Ersetzung durch s/^\t//, bei der eine führende Registerkarte entfernt wird, falls vorhanden, und (b) drucken ( p) die Zeile.

John1024
quelle
7

Ein einfacher Bash / Sed-Ansatz:

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

Das while read w; do ...; done < wordswird über jede Zeile in der Datei iterieren wordsund sie unter speichern $w. Die -nMarken seddrucken standardmäßig nichts. Der sedBefehl ersetzt dann doppelte Anführungszeichen, gefolgt von Nicht-Leerzeichen ( \"(\S*)die Klammern dienen dazu, zu erfassen, was mit \S*dem ersten Wort übereinstimmt , und wir können es später als bezeichnen \1), 0 oder mehr Zeichen ( .*) und dann das Wort, nach dem wir suchen ( $w) und wieder 0 oder mehr Zeichen ( .*). Wenn dies übereinstimmt, ersetzen wir es nur durch das erste Wort, einen Tabulator und $w( \1\t$w) und drucken die Zeile (das ist, was der pEingang s///ptut).

Terdon
quelle
5

Dies ist die Ruby-Version

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

Die Beispieltextdatei hello.txtenthält

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

Laufen mit ruby source.rb hello.txtErgebnissen in

This    text
Another thing
It      try
Better
Anwar
quelle