Bashスクリプトでテキストが最初に表示される行番号を見つける

Bashスクリプトでテキストが最初に表示される行番号を見つける

テキストファイルの行の先頭にある特定の検索文字列が最初に表示される行番号を見つけて、私のbashスクリプトの変数に保存する必要があります。たとえば、「c」が最初に表示されるものを探したいとします。

abc
bde
cddefefef // this is the line that I need its line number
Casdasd // C here is capital, I dont need it
azczxczxc
b223r23r2fe
Cssdfsdfsdf
dccccdcdcCCDcdccCCC
eCCCCCC

これを思い出しましたが、ご覧のように問題が大きいです。

   trimLineNum=$(cat "${varFileLog}" | grep -m1 -n "c")
   echo "c is at line #"${trimLineNum}

出力は次のとおりです。

c is at line #1:abc

質問:

  1. その行に「c」があるので、明らかに最初の行と一致します。
  2. 出力にはその行の内容も含まれます!私はそれが行番号だけでありたいです。

これらの問題を解決するには、何を変更する必要がありますか?

答え1

POSIXでは、sed通常の出力を抑制するオプションを使用でき、-n(pattern)で始まる行の場合とuitを使用して行番号を印刷できます。c^c=q

sed -n '/^c/{=;q;}'

GNUを使用すると、コマンドをsed使用して出力なしで終了し、次に単純化できます。Q

sed '/^c/!d;=;Q'

答え2

複数のソリューションが存在します

awkで

awk '/^c/ { print NR; exit}' "${varFileLog}"
  • /^c/:次から始まる行と一致します。c
  • print NR:レコード(ライン)番号の印刷
  • exit:処理を続行しません

予想通り、awkこれが私が好む解決策です。

grep + フィルタの使用

grep -n '^c' "${varFileLog}" | head -n1 | sed 's/:.*//'
  • '^c':次から始まる行と一致します。c
  • head -1: grep 結果の最初の行のみを表示
  • sed 's/:.*//':後で何でも削除:

sed 's/:.*//'この場合もcut -d: -f1同じ効果があります

パフォーマンス情報

Stephenのソリューションよりも遅くなる可能性があります。

grep -m1 -n '^c' "${varFileLog}" | cut -d: -f1

答え3

grep一致を行の先頭に固定して、「行の先頭になければならない」制約を考慮する必要があります^

trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")

その後、ポストプロセスの出力には行grep番号のみが保持されます。

trimLineNum=$(grep -m1 -n -- '^c' "${varFileLog}")
trimLineNum="${trimLineNum%%:*}"

これは-mGNU拡張です(GNUの場合、GNUはオプションではなく引数の後でもオプションを受け入れるため、偶数で始めるgrep必要はありません)。標準的に出力を 。--^c--$varFileLog-grephead -n 1

一致するものがない場合、最初のコマンドはfalse / failを返し、2番目のコマンドはpipefail複数のシェル(bash

答え4

使用幸せ(以前のPerl_6)

raku -ne 'state $i; ++$i; say "c starts line $i" and last if m/^c/;'  

または

raku -ne 'state $i; ++$i; say "c starts line $i" and last if (.index("c").defined && .index("c") == 0);' 

または

raku -ne 'state $i; ++$i; say "c starts line $i" and last if .starts-with("c");' 

出力:

c starts line 3

-neRaku(ライン別非自動印刷)コマンドラインフラグを使用します。行番号を取得するには、state変数を$i一度初期化してから行を読むたびにインクリメントします。 "c"行の先頭が識別されると(正規表現または、indexまたはでstarts-with)文字列が"c starts line $i"補間されて出力されます(say)。

as last注:上記の各例には、優先順位の低い条件が追加されました。一致するすべての行番号を返すには、この条件を削除してください。例:

~$ raku -ne 'state $i; ++$i; say "c starts line $i" if m/^c/;'  file
c starts line 3
c starts line 10

付録:ありがとうこの回答、Rakuルーチンを使用して「c」で始まるゼロインデックスの最初の行番号を取得する簡単な方法は次のとおりですfirst

~$ raku -e 'say lines.first(* ~~ / ^ c /):k;' file
2

#OR

~$ perl6 -e 'say lines.first(*.starts-with("c")):k;'  file
2

入力例:

abc
bde
cddefefef // this is the line that I need its line number
Casdasd // C here is capital, I dont need it
azczxczxc
b223r23r2fe
Cssdfsdfsdf
dccccdcdcCCDcdccCCC
eCCCCCC
cddefefef // this is the line that I need its line number (again)

https://raku.org

関連情報