1

やあ、

過去数日間、stackoverflow (素晴らしいリソース!) で多くの検索を行ったおかげで、これに成功し、次の問題にも成功しました。これは、コマンドを実行するたびに出力が 2 倍になるという結果でした。二重線を削除できた awk コマンドのおかげです。検索はかなり進んでいますが、1 つのオプションがありません。ちなみにMacosXとLinuxの両方を使用しています。

私がやろうとしているのは、メモ(すべてプレーン テキストの .md ファイル)を解析し、テキスト ファイル(greplist.txt と呼ばれる)で単語/タグを検索し、同じ名前の別のテキスト ファイルで一致する行を解析することです。検索ワード/タグ(例: @computer.md) .

greplist.txtの内容の選択は次のとおりです。

@home
@computer
@Next
@Waiting

2 つの .md ファイルの内容の例:

学校.md:

* find lost schoolbooks @home
* do homework @computer

楽しい.md

* play videogame @computer

この端末コマンドを使用すると(うまく機能しますが、まだ完全ではありません)

$ cat greplist.txt | while read line; do grep -h "$line" *.md >> $line.md.tmp; mv $line.md.tmp $line.md; awk '!x[$0]++' < $line.md > $line.md.tmp && mv $line.md.tmp $line.md ;done

結果

@computer.mdの結果:

* do homework @computer
* play videogame @computer

@home.mdは次のようになります。

* find lost schoolbooks @home

これまでのところとても素晴らしいです!もうこれで本当に幸せです。特に、ファイルの移動/名前変更が追加されたため、@ tag .md ファイルに追加のタスク/行を追加し、次にコマンドを実行したときに上書きされることなくファイルに含めることもできます。素晴らしいケーキ!

今私が見逃している唯一のことは、タスクの背後にある@ tag .mdファイルの出力でも、出力が検索結果の後ろの括弧の間にファイル名(拡張子なし)をリストすることを望むことです(nvaltがこれを次のように使用できるように)内部リンク)

したがって、例@computer.mdの望ましい出力は次のようになります。

* do homework @computer [[school]]
* play videogame @computer [[fun]]

-h の代わりに grep コマンドで -l と -H を使用してこれをいじってみましたが、出力がどうにか乱雑になります。(まだブラケットを追加しようとさえしていません!)

私が試した別のこれはこれでしたが、継ぎ目は何もしません。ただし、おそらく私が達成しようとしていることを示しています。

$ cat greplist.txt | while read line; do grep -h "$line" *.md | while read filename; do echo "$filename" >> $line.md.tmp; mv $line.md.tmp $line.md; awk '!x[$0]++' < $line.md > $line.md.tmp && mv $line.md.tmp $line.md ;done

したがって、ジンバブエ 100 万ドルの問題は次のとおりです。これをどのように行うか。試してみましたが、これは私のスキルレベル atm を超えています。解決策を見つけることに非常に熱心です!

前もって感謝します。

ダニエル・デニス・デ・ウィット

4

2 に答える 2

2

これを試してください:

grep -f greplist.txt *.md | awk ' match($0, /(.*).md:(.*)(@.*)/, vars) { print vars[2], "[[" vars[1] "]]" >> vars[3]".md.out"} '

機能:

grepは、一致したパターンを.mdファイルのgreplist.txtに出力します。

fun.md:* play videogame @computer
school.md:* find lost schoolbooks @home
school.md:* do homework @computer

最後に、 awkはファイル名を必要な形式で後ろに移動し、各行を対応する@ .md.out* ファイルに追加します。

* play videogame @computer [[fun]]
* find lost schoolbooks @home [[school]]
* do homework @computer [[school]]

次回コマンドを実行するときに @* ファイルが含まれないように、ファイル名に.outを追加しました。

awkスクリプトが Mac OS X awk で動作するかどうかはわかりません。

于 2013-09-17T09:48:22.533 に答える
2

アウトライン ソリューションは、コードを記述するためのかなり長い方法のように思えます。このスクリプトは、 を使用してスクリプトsedを記述しawk、次に実行awkして、標準入力からプログラムを読み取り、..mdで始まらないすべての ' ' ファイルに適用します@

sed 's!.*!/&/ { name=FILENAME; sub(/\\.md$/, "", name); printf "%s [[%s]]\\n", $0, name > "&.md" }!' greplist.txt |
awk -f - [!@]*.md

Mac OS X 上の のバージョンはawk、標準入力からプログラムを読み取ります。GNU も同様awkです。したがって、パイプにプログラムを書き、パイプからプログラムを読み取るという手法は、これらのバージョンで機能します。最悪の場合は、出力をsed一時ファイルに保存し、一時ファイルawkからプログラムを読み取ってから、一時ファイルを削除する必要があります。を に置き換えるのは簡単なsedのでawk、1 つのawkプロセスでawkプログラムを作成し、2 つ目のawkプロセスでプログラムを実行します。

生成されたawkコードは次のようになります。

/@home/ { name=FILENAME; sub(/\.md$/, "", name); printf "%s [[%s]]\n", $0, name > "@home.md" }
/@computer/ { name=FILENAME; sub(/\.md$/, "", name); printf "%s [[%s]]\n", $0, name > "@computer.md" }
/@Next/ { name=FILENAME; sub(/\.md$/, "", name); printf "%s [[%s]]\n", $0, name > "@Next.md" }
/@Waiting/ { name=FILENAME; sub(/\.md$/, "", name); printf "%s [[%s]]\n", $0, name > "@Waiting.md" }

!スクリプトでの の使用はsed、生成されたスクリプトに表示されない文字を選択するだけです。各行でファイルのベース名を決定することは「効率的」ではありません。ファイルが十分に大きい場合は、次のような行を追加できます。

{ if (FILENAME != oldname) { name = FILENAME; sub(/\.md$/, "", name); oldname = FILENAME } }

スクリプトの最初までawk(それを行う方法はいくつ考えられますか?)。その後、 の行ごとの設定を削除できますname

@topic.mdファイルに対してプログラムを実行しようとしないでください。それは混乱につながります。

于 2013-09-17T14:36:27.217 に答える