Друкувати слово, що містить рядок та перше слово


10

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

Наприклад:

"Це єдиний текстовий рядок"
"Ще одна річ"
"Краще спробуйте ще раз"
"Краще"

Список рядків:

текст
річ
спробуйте
Краще

Я намагаюся отримати таку таблицю:

Це [вкладка] тексту
Ще одна [вкладка] річ
Спробуйте [вкладка]
Краще

Я намагався з грепом, але нічого не сталося. Будь-яка пропозиція?


Отже, в основному "Якщо рядок має рядок, надрукуйте перше слово + рядок". Правильно?
Сергій Колодяжний

Відповіді:


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

Перл на допомогу!

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

Ось версія пітона:

#!/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 (викликається gsedOSX). Для 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визначає мітку a. Отже, якщо знайдено одне з ваших слів, ми (а) робимо заміну, s/^\t//яка видаляє провідну вкладку, якщо така є, і (b) друкує ( 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), і надрукувати рядок (це те , що pв 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.