Распечатать слово, содержащее строку и первое слово


10

Я хочу найти строку в строке текста и распечатать строку (между пробелами) и первое слово фразы.

Например:

«Это одна строка текста»
"Еще одна вещь"
"Лучше попробуй еще раз"
"Лучше"

Список строк:

текст
предмет
пытаться
Лучше

Я пытаюсь получить такую ​​таблицу:

Этот [вкладка] текст
Еще одна [вкладка] вещь
Это [вкладка] попробуйте
Лучше

Я пытался с grep, но ничего не произошло. Любое предложение?


Итак, в основном «Если в строке есть строка, выведите первое слово + строка». Правильно ?
Сергей Колодяжный

Ответы:


12

Версия 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

Назовите это так:

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

Вывод:

This    text
Another thing
It  try
Better

9

Perl на помощь!

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

Сохранить как first-plus-word, запустить как

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

Это создает регулярное выражение из входных слов. Затем каждая строка сопоставляется с регулярным выражением, и, если есть совпадение, печатается первое слово, и если оно отличается от слова, слово печатается тоже.


9

Вот версия 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список слов и file1содержит фразы.


2
Неплохо! Я поместил его в файл сценария paste.ubuntu.com/23063130 , просто для удобства
Сергей Колодяжный

8

Вот версия 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

Примечание стороны : Скрипт python3совместим, так что вы можете запустить его либо python2или python3.


7

Попробуй это:

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

Если перед вкладкой Betterесть проблема, попробуйте это:

$ 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

Выше был протестирован на GNU SED (называется gsedна OSX). Для BSD sed могут потребоваться некоторые незначительные изменения.

Как это устроено

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

    Это ищет слово, [[:alnum:]]+сопровождаемое пробелом, [[:space:]]сопровождаемое чем угодно .*, сопровождаемое одним из ваших слов text|thing|try|Better, сопровождаемое чем угодно. Если он найден, он заменяется первым словом в строке (если есть), вкладкой и соответствующим словом.

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

    Если команда подстановки привела к подстановке, что означает, что одно из ваших слов было найдено в строке, то taкоманда сообщает sed перейти к метке a. Если нет, то мы переходим ( b) к следующей строке. :aопределяет метку а. Итак, если одно из ваших слов было найдено, мы (а) делаем замену, s/^\t//которая удаляет ведущую вкладку, если она есть, и (б) печатаем ( p) строку.


7

Простой подход 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 < wordsБудет перебирать каждую строку в файл wordsи сохранить его как $w. В -nмарке sedничего по умолчанию не печатает. Затем sedкоманда заменит двойные кавычки, за которыми следуют непробельные символы ( \"(\S*)круглые скобки служат для «захвата» того, что соответствует \S*, первое слово, и мы можем позже сослаться на него как \1), 0 или более символов ( .*), а затем слово, которое мы ищем ( $w) и 0 или более символов снова ( .*). Если это совпадает, мы заменяем его только 1-м словом, табуляцией и $w( \1\t$w), и печатаем строку (это то, что делает pin s///p).


5

Это версия 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

Образец текстового файла hello.txtсодержит

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

Запуск с ruby source.rb hello.txtрезультатами в

This    text
Another thing
It      try
Better
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.