In từ chứa chuỗi và từ đầu tiên


10

Tôi muốn tìm một chuỗi trong một dòng văn bản và in chuỗi (giữa các khoảng trắng) và từ đầu tiên của cụm từ.

Ví dụ:

"Đây là một dòng văn bản duy nhất"
"Cái khác"
"Tốt hơn là bạn thử lại"
"Tốt hơn"

Danh sách các chuỗi là:

bản văn
Điều
thử
Tốt hơn

Những gì tôi đang cố gắng để có được một bảng như thế này:

Văn bản [tab] này
Một điều [tab] khác
Nó [tab] thử
Tốt hơn

Tôi đã thử với grep nhưng không có gì xảy ra. Bất kì lời đề nghị nào?


Vì vậy, về cơ bản "Nếu dòng có chuỗi, hãy in từ + chuỗi đầu tiên". Đúng ?
Sergiy Kolodyazhnyy

Câu trả lời:


12

Phiên bả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

Gọi nó như vậy:

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

Đầu ra:

This    text
Another thing
It  try
Better

9

Perl để giải cứu!

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

Lưu dưới dạng first-plus-word, chạy như

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

Nó tạo ra một regex từ các từ đầu vào. Mỗi dòng sau đó được khớp với biểu thức chính quy và nếu có một từ trùng khớp, từ đầu tiên được in và nếu nó khác với từ đó, thì từ đó cũng được in.


9

Đây là phiên bả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

nơi file2đây là danh sách từ và file1chứa các cụm từ.


2
Tốt một! Tôi đã đặt nó vào một tập tin tập lệnh, paste.ubfox.com/23063130 , để thuận tiện
Sergiy Kolodyazhnyy

8

Đây là phiên bản 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("")

Bản giới thiệu:

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

Lưu ý bên lề : Tập lệnh python3tương thích, vì vậy bạn có thể chạy nó với python2hoặc python3.


7

Thử đi:

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

Nếu tab trước đó Betterlà một vấn đề, thì hãy thử điều này:

$ 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

Ở trên đã được thử nghiệm trên GNU sed (được gọi là gsedOSX). Đối với sed BSD, một số thay đổi nhỏ có thể được yêu cầu.

Làm thế nào nó hoạt động

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

    Điều này tìm kiếm một từ, [[:alnum:]]+theo sau là khoảng trắng [[:space:]], tiếp theo là bất cứ thứ gì .*, theo sau là một trong những từ của bạn text|thing|try|Better, theo sau là bất cứ thứ gì. Nếu điều đó được tìm thấy, nó được thay thế bằng từ đầu tiên trên dòng (nếu có), một tab và từ phù hợp.

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

    Nếu lệnh thay thế dẫn đến thay thế, có nghĩa là một trong những từ của bạn đã được tìm thấy trên dòng, thì talệnh sẽ cho sed nhảy sang nhãn a. Nếu không, sau đó chúng ta rẽ nhánh ( b) sang dòng tiếp theo. :ađịnh nghĩa nhãn a. Vì vậy, nếu một trong những từ của bạn được tìm thấy, chúng tôi (a) thực hiện thay thế s/^\t//sẽ loại bỏ một tab hàng đầu nếu có một từ và (b) in ( p) dòng.


7

Một cách tiếp cận bash / sed đơn giản:

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

Các while read w; do ...; done < wordssẽ lặp qua mỗi dòng trong file wordsvà lưu nó như là $w. Làm -ncho sedkhông in bất cứ điều gì theo mặc định. Sau sedđó, lệnh sẽ thay thế các dấu ngoặc kép theo sau là khoảng trắng ( \"(\S*), dấu ngoặc đơn dùng để "nắm bắt" những gì được khớp bởi \S*, từ đầu tiên và sau đó chúng ta có thể gọi nó là \1), 0 hoặc nhiều ký tự ( .*) và sau đó là từ chúng tôi đang tìm kiếm ( $w) và 0 hoặc nhiều ký tự trở lại ( .*). Nếu điều này khớp, chúng tôi chỉ thay thế nó bằng từ 1, tab và $w( \1\t$w) và in dòng (đó là những gì ptrong s///pđó).


5

Đây là phiên bả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

Tệp văn bản mẫu hello.txtchứa

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

Chạy với ruby source.rb hello.txtkết quả trong

This    text
Another thing
It      try
Better
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.