同じ文字で開始および終了するすべての行を表示するgrepコマンド


回答:


14

POSIXly:

pattern='\(.\).*\1
.'
grep -x -- "$pattern" file

あなたがそのケースをカバーしたい場合はラインが開始または無効なバイト文字で終わるが、あなたが追加できるかどうかは動作しませんLC_ALL=Cが、LC_ALL=Cシングルバイト文字データのみで動作します。


perl6 あなたがあなたの箱にそれを持っているならば、それは最高のツールのようです:

$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
  perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1

それでも無効な文字で窒息しますが。


フォームにperl6変換してテキストを変更することに注意してくださいNFC

$ printf '\u0044\u0323\u0307\n' |
  perl6 -pe ''                  |
  perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a

$ printf '\u0044\u0323\u0307\n' |
  perl -pe ''                   |
  perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a

内部的には、perl6文字列をのNFG形式(の略Normalization Form Grapheme)で格納します。これは、perl6事前に構成されていない書記素を適切に処理するために発明された方法です。

$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2

2
PerlによるUnicodeテキストの処理は、Perlの多くの「単純な」タスクが、少なくとも同じレベルの正確さで他のツールを使用して実装することが実際には不可能であるという点で、模範例に過ぎません。
ディートリッヒエップ2016

1
perl6ただし、テキストが変更されることに注意してください(NFC(正規化フォーム「構成済み」)に変更)。
ステファンChazelas

@StéphaneChazelas:はい。また、文字列in perl6NFGGfor Grapheme)の形式で格納されることに注意してください。これは、perl6事前に構成されていない書記素を適切に処理する方法です。
cuonglm 2016

10

grepではなくawk:

awk -F "" 'NF && $1 == $NF'

これらの特別なケースが処理されます:

  • 空の行は印刷されません
  • 常に1文字の行を印刷します

空のFSは、フィールドごとに一つの文字にレコードを分割しgawkmawkそしてbusybox awk(バイトではなく、後者の二つのための文字)が、の実装では動作しない標準的ではないとしawk、A、WおよびK等により元の1つに由来しますBSDおよび商用Unices。移植性は高くなりますが、入力する必要があります:

awk '/./ && substr($0,1,1) == substr($0,length)'

1
FS空の文字列は標準ではなく、一部のawk実装では機能しないことに注意してください。
cuonglm 2016

2
分割を回避し、完全に移植可能な代替手段awk 'length&&substr($0,1,1)==substr($0,length)'length$0{print $0}
最悪の

@ dave_thompson_085:thx、私はデフォルトのアクションヒントを使用して、コマンドを最短にしています。
rudimeier 2016

ファーン。1つのマイナーな修正。Solarisの古いawkのテストは間違っていました(誤ってxpg4をオンにしました)が、この方法nawkはほとんど同じように機能します:-)
dave_thompson_085

8
grep -xe '\(.\).*\1' -e .

例:

$ printf '%s\n' il y était cet été  | grep -xe '\(.\).*\1' -e .
y
été

-x以下のためにあるの正確な一致(全体のライン上の一致)。\1でキャプチャされた文字への後方参照\(.\)です。-e .単一の文字を含む行の特殊なケースを処理するためにaを追加します。

入力に現在のロケールで有効なテキストが含まれていると想定しています。

一致は文字ではなく、バイト(UTF-8のéは2バイト0xc3 0xa9です)、書記素クラスタ(これらのéが分解形式で記述され、eその後にU + 0301が付いている場合)ではありませんたとえば、アキュートアクセントを組み合わせます)。

PCRE grepをサポートするを使用して書記素クラスターで作業するに-Pは:

$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été

これは、2つのクラスターの分解が同じであることを前提としています。たとえば、はまたは()または()またはḉ()として表現されたものc U+0301 U+0327と一致しません。そのためには、正規化されたフォームでチェックを行う必要があります。c U+0327 U+0301ćU+0107U+0327çU+00E7U+0301U+1E09

$ printf '\ue7\u301 blah \u107\u327\n' |
  perl -MUnicode::Normalize -C -ne '
    print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ

1
をお持ちの場合はperl6perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'すべての作業を行う必要があります。
cuonglm 2016

1

python2の代替案:

python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt

例:

$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt  | cat -A 
nathan$
 ookie $
a line a$

行に末尾または先頭のスペースが含まれている場合は失敗します(例: `121`)。
cuonglm 2016

本当です@cuonglm。しかし、空白を末尾または先頭に置くことが要件でしたか?これは求められる仕事をします-先頭と最後の文字が同じかどうかを確認します。空白はまだASCII文字です。
Sergiy Kolodyazhnyy 2016

ちなみに、@ cuonglm yoursは、後続スペースと先行スペースでも失敗しました:)
Sergiy Kolodyazhnyy

コードによって先頭と末尾の空白が削除されるため、入力行が変更されます。また、空行の場合はエラーになります。
rudimeier 2016

@セルグ:どうやって?私の答えはグレッピングだけです、それは入力を変更しません。
cuonglm 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.