特定の「文字列」を見つけて行全体を印刷するにはどうすればよいですか?

特定の「文字列」を見つけて行全体を印刷するにはどうすればよいですか?

myfile.csv次の内容のファイルがあります。

 abc:123:myname:1231
 def:423324:arbitrary:value:string
 StackExchange:Unix:Linux

私が実行している端末で./myscript.sh def

内容はmyscript.sh次のとおりです。

#!/bin/bash
key_word_I_am_looking_for=$1
my_variable=`cat myfile.csv | awk -F: -v keyword="$key_word_I_am_looking_for" '( $1 == keyword )' END{print "$@" }'`
echo "$my_variable"

コードdefmyfile.csvIEabcまたはStackExchange.出力は)になります。my_variabledef 423324 arbitrary value string./myscript.sh def./myscript.sh StackExchangeStackExchange Unix Linux

私はどこで間違っていますか?他のオプションがありますか?

答え1

awk構文が少し間違っています。

#!/bin/bash
awk -F: -v keyword="$1" '$1 == keyword {$1=$1; print}' myfile.csv

ここでの秘密は、フィールドの1つの値を再割り当てして、awkに出力ファイル区切り文字を使用して$ 0を再計算することです。ここでデフォルトのOFSは空白なので、$ 1の値をそれ自体に割り当てると、コロンは空白に変わります。

それを書くための有益な方法は次のとおりです。

grep "^$1:" myfile.csv | tr ":" " "

ただし、これは文字列平等ではなく正規表現の一致を使用します。

答え2

代替方法は次のとおりですsed

sed -n '/^def:/s/:/ /gp' myfile.csv

文字列を最初の位置引数として渡す場合:

sed -n "/^$1:/s/:/ /gp" myfile.csv

答え3

Pythonで。

$ python -c "import sys;
with open(sys.argv[2]) as f:
    for line in f:
        if sys.argv[1] == line.split(':')[0]:
            print ' '.join(line.strip().split(':'))" def file
def 423324 arbitrary value string

端末で上記のスクリプトを実行し、検索キーワードを最初の引数に、ファイル名を2番目の引数に渡します。

答え4

Raku(以前のPerl_6)の使用

raku -ne '.put if .=split(":")[0] eq "def";' myfile.csv

出力:

def 423324 arbitrary value string

言語に関する注意:Perl言語シリーズは「トピック」変数の概念を利用します。 Rakuはこの概念を拡張して標準化します(下記Rosettaコードリンクを参照)。ルーチンはデフォルトで$_テーマ変数を使用するため、タスクを表示するには前のピリオドのみが必要です。存在するトピック$_変数上記のコードを「手で直接書く」と、実際に次のような結果が得られます。

raku -ne '$_.put if $_.=split(":")[0] eq "def";'

最後にラクが提案します。.= バイナリ割り当て=lvalueを更新するには、デフォルトで(等号)を挿入するだけの演算子です。したがって、コードを.shortermy $temp = $_.fn(…); $_ = $temp;に圧縮することができ、一時変数を$_.=fn(…) 作成する必要はありません!$temp

https://rosettacode.org/wiki/Topic_variable#Raku
https://docs.raku.org/routine/.=
https://raku.org/

関連情報