テキスト行で文字列を検索し、その文字列(スペースの間)とフレーズの最初の単語を印刷したい。
例えば:
「これは単一のテキスト行です」 "別物" 「もう一度やり直してください。」 「良い」
文字列のリストは次のとおりです。
テキスト 事 試す より良い
私が試みているのは、このようなテーブルを取得することです:
この[タブ]テキスト 別の[タブ]事 [タブ]試してみる より良い
grepを試しましたが、何も起こりませんでした。なにか提案を?
テキスト行で文字列を検索し、その文字列(スペースの間)とフレーズの最初の単語を印刷したい。
例えば:
「これは単一のテキスト行です」 "別物" 「もう一度やり直してください。」 「良い」
文字列のリストは次のとおりです。
テキスト 事 試す より良い
私が試みているのは、このようなテーブルを取得することです:
この[タブ]テキスト 別の[タブ]事 [タブ]試してみる より良い
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
入力した単語から正規表現を作成します。次に、各行が正規表現と照合され、一致がある場合は最初の単語が出力され、単語と異なる場合はその単語も出力されます。
これが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
。
これを試して:
$ 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:]]
、続いて何か.*
、続いて自分の単語の1つ、続いて何かを探しますtext|thing|try|Better
。見つかった場合は、行の最初の単語(ある場合)、タブ、および一致した単語に置き換えられます。
ta; b; :a; s/^\t//; p
置換コマンドによって置換が行われた場合、つまり、単語の1 ta
つが行で見つかった場合、コマンドはsedにlabelにジャンプするように指示しa
ます。そうでない場合は、b
次の行に分岐します()。 :a
ラベルを定義します。したがって、単語の1つが見つかったs/^\t//
場合は、(a)先行タブがある場合はそれを削除する置換を行い、(b)p
行を印刷()します。
単純な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個以上の文字(.*
)。これが一致する場合は、最初の単語、タブと$w
(\1\t$w
)だけに置き換えて、行を出力します(それがp
inのs///p
動作です)。
これは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