Я хочу найти строку в строке текста и распечатать строку (между пробелами) и первое слово фразы.
Например:
"This is a single text line" "Another thing" "It is better you try again" "Better"
Список строк:
text thing try Better
То, что я пробую, должно получить таблицу как это:
This [tab] text Another [tab] thing It [tab] try Better
Я попробовал grep, но ничто не произошло. Какое-либо предложение?
Версия 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
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
, Это создает regex из входных слов. Каждая строка затем подобрана против regex, и если существует соответствие, первое слово печатается, и если это отличается от слова, слово печатается, также.
Попробуйте это:
$ 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
определяет маркировку a. Так, если одно из Ваших слов было найдено, мы (a) делаем замену s/^\t//
, который удаляет ведущую вкладку, если существует один и (b) печатаем (p
) строка.
Это - версия
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
Ruby, которую демонстрационный текстовый файл 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
Вот 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
содержит фразы.
Вот версия 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
.
Простой подход 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
делает).