Pythonで一般的なbashイディオムを実装する方法は?[閉まっている]


242

私は現在、よく覚えていないAWK、sed、Bash、およびほんの少しのPerlを使用してテキストファイルを操作しています。

私はpythonがこの種のことのために良いいくつかの場所について言及するのを見ました。Pythonを使用して、シェルスクリプト、AWK、sedなどを置き換えるにはどうすればよいですか?


3
pythonpyはawkの優れたライバルであり、python構文を使用してsedです:github.com/Russell91/pythonpy
RussellStewart


これは私の質問です。なぜそれが意見に基づいているのかわかりません。一番上の答えは、シェルが行う主なことをそれぞれリストし、それらをpythonで行う方法を説明しています。私の意見では、この意見には意見がありません。
クリスジェファーソン

この質問とそれの締めくくりは、ここ
Erik A

回答:


144

どのシェルにもいくつかの機能セットがあります。

  • Essential Linux / Unixコマンド。これらはすべてサブプロセスライブラリから利用できます。これは、すべての外部コマンドを実行するための最良の最初の選択肢とは限りません。個別のLinuxコマンドであるいくつかのコマンドについては、shutilも参照してください。ただし、Pythonスクリプトに直接実装することもできます。Linuxコマンドの別の巨大なバッチはosライブラリにあります。これらはPythonでより簡単に実行できます。

    そして-ボーナス!-より迅速に。シェル内の個別のLinuxコマンド(いくつかの例外はあります)は、サブプロセスをフォークします。Python shutilosモジュールを使用することで、サブプロセスをフォークしません。

  • シェル環境機能。これには、コマンドの環境を設定するものが含まれます(現在のディレクトリと環境変数、その他)。これはPythonから直接簡単に管理できます。

  • シェルプログラミング機能。これは、すべてのプロセスステータスコードチェック、さまざまなロジックコマンド(if、while、forなど)、テストコマンド、およびそのすべての関連コマンドです。関数定義のもの。これは、Pythonでははるかに簡単です。これは、bashを削除してPythonで実行する際の大きな勝利の1つです。

  • 相互作用機能。これには、コマンド履歴と何も含まれません。シェルスクリプトを書くためにこれは必要ありません。これは人間の相互作用のためだけであり、スクリプトを書くためではありません。

  • シェルファイル管理機能。これには、リダイレクトとパイプラインが含まれます。これはトリッキーです。これの多くはサブプロセスで行うことができます。しかし、シェルでは簡単なことの一部は、Pythonでは不愉快です。特にのようなもの(a | b; c ) | something >result。これにより、2つのプロセスが並列に実行され(出力はaへの入力としてb)、3番目のプロセスが続きます。そのシーケンスからsomethingの出力はと並行して実行され、出力はという名前のファイルに収集されますresult。他の言語で表現するのは複雑です。

特定のプログラム(awk、sed、grepなど)は、Pythonモジュールとして書き直すことができます。行き過ぎないでください。必要なものを置き換えて、「grep」モジュールを進化させます。「grep」を置き換えるPythonモジュールの作成を始めないでください。

最良のことは、これを段階的に実行できることです。

  1. AWKとPERLをPythonに置き換えます。他はすべて放っておいてください。
  2. GREPをPythonで置き換える方法を見てください。これはもう少し複雑になる可能性がありますが、GREPのバージョンは処理のニーズに合わせて調整できます。
  3. FINDをを使用するPythonループに置き換える方法を見てくださいos.walk。多くのプロセスを生成しないので、これは大きな勝利です。
  4. 一般的なシェルロジック(ループ、決定など)をPythonスクリプトで置き換える方法を見てください。

6
「インタラクション機能。これには、コマンド履歴と何も含まれません。これは必要ありません。」人が本当に必要とするものかどうかは誰にもわからないと思います。おそらく彼はそうします。さらに、これらの機能は、IdleとIPythonの違いを例に取ると、対話型シェルでは非常に意味があります。
heltonbiker

47
シェルスクリプトをすべて廃止してほしいと思います。ハッキングは実質的に* nixの世界では宗教であることを理解していますが、OSに埋め込まれたすべてのハッキングの回避策を解釈しようとすることにうんざりしています。microtoolの目新しさ(awk、sed、top、baseなど)は、誰もが独自のバージョンをロールすることを決めた日にオフになりました。適切に設計された2つのPythonモジュールで簡単に置き換えることができる、くだらない小さなツールに費やされる工数が想像できるとき、私はうんざりしています。::ため息::
Evan Plaice

40
findが持っているいくつかのスクリプトのpythonバージョンは、醜くて長く、比較してメンテナンスができないため、@ EvanPlaiceに同意しません。多くのものシェルスクリプトであるべきで、他のものはそうではありません。すべてがPythonまたはBASH(またはその他)の1つだけである必要はありません。
mikebabcock

8
@mikebabcock理想的には、基本的な* nixスタックによって提供されるすべてのマイクロツールを実装する完全なライブラリがあるでしょう。find()やlast()などの関数が含まれ、パイプの代わりに、カリー化とレイジーロードの組み合わせにより、すべての結合が処理されます。すべてのディストリビューションで標準的な方法で動作するPOSIXスクリプティング環境があればいいのではないでしょうか。そのようなものはまだ存在しません...
エヴァン・プレース

2
シェルパイプライン(例えば、約点(a | b; c ) | something >result)、ややそれがシェルのパイプラインを通過する自明容易であることによって緩和されるsubprocess方法を用いてshell=True
iruvar

103

はい、もちろん :)

シェルスクリプト二度と作成しないために役立つこれらのライブラリを見てください(Plumbumのモットー)。

また、awk、sed、grepをPythonベースの何かで置き換えたい場合は、pypをお勧めします -

「The Pyed Piper」、またはpypは、awkまたはsedに似たLinuxコマンドラインテキスト操作ツールですが、標準のpython文字列とリストメソッド、およびカスタム関数を使用して、強力な本番環境で高速な結果を生成します。



57

私はbashとipythonの優れた部分を組み合わせる方法を発見しました。今のところ、これはサブプロセスなどを使用するよりも快適に思えます。既存のbashスクリプトの大部分を簡単にコピーして、たとえばPythonの方法でエラー処理を追加できます:)そして、これが私の結果です:

#!/usr/bin/env ipython3

# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy    # creates new ipy-file
#
# 2. chmod +x scriptname.ipy                            # make in executable
#
# 3. starting with line 2, write normal python or do some of
#    the ! magic of ipython, so that you can use unix commands
#    within python and even assign their output to a variable via
#    var = !cmd1 | cmd2 | cmd3                          # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
#    but parses raw python fine, please check again for the .ipy suffix

# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
  !echo $file | grep "p"
# sorry for this nonsense example ;)

システムシェルコマンドシステムシェルとしての使用に関するIPythonドキュメントを参照してください。


11
何らかの奇妙な理由のために、絶対に鍵となるIPythonの!-コマンドに言及した人はいないため、賛成です。特に、次のように変数(行のリスト)に出力を割り当てることもできるためfilelines = ! cat myfile
kampu

そして$var、シェルコマンドのようにPython変数を使用できますか?ワオ。これは受け入れられる答えになるはずです。
Chiel ten Brinke 2016年

また、jupyterノートブック内からも使用できます
Yuval Atzmon

44

2015年とPython 3.4のリリース以降、http//xon.sh/またはhttps://github.com/scopatz/xonshで利用可能な合理的な完全なユーザーインタラクティブシェルが利用可能になりました。

デモビデオはパイプが使用されて表示されませんが、ときに、デフォルトのシェルモードでそれらがサポートされています。

Xonsh( 'conch')はbashをエミュレートするために非常に一生懸命試みます。

env | uniq | sort -r | grep PATH

または

my-web-server 2>&1 | my-log-sorter

引き続き正常に動作します。

チュートリアルは非常に長く、誰かが通常ashまたはbashプロンプトで期待する機能のかなりの部分をカバーしているようです:

  • コンパイル、評価、実行!
  • コマンド履歴とタブ補完
  • ヘルプ&Superhelp ???
  • エイリアスとカスタマイズされたプロンプト
  • *.xshインポート可能なコマンドやスクリプトを実行します
  • ルックアップを含む環境変数 ${}
  • 入力/出力のリダイレクトと結合
  • バックグラウンドジョブとジョブ制御
  • サブプロセス、パイプ、およびコプロセスのネスト
  • コマンドが存在する場合はサブプロセスモード、それ以外の場合はPythonモード
  • でキャプチャされたサブプロセス、$()でキャプチャされていないサブプロセス$[]、Pythonで評価@()
  • ファイル名グロブ*または正規表現ファイル名グロブバックバック

しかし、なぜこれらすべての答えが、bashを知らない人のためのホイール再発明しているだけのように思われるのですか?私はbashに適度に慣れてきました。これらの答えはどれも、ほとんど利益を得るためにさらに多くの作業を行うことになるようです。これらの回答はすべて、bashを恐れている(または学習に時間をかけたくない)Pythonの人々を対象としています。そうですか?
Buttle Butkus 2017

それは要件のようないくつかの欠点が使用しているようだ.xsh:xonshコードでファイルの拡張子をgithub.com/xonsh/xonsh/issues/2478。それ以外の場合はevalx.pyファイルから直接呼び出すために使用する必要があります。
Andry

31
  • Pythonをシェルとして使用したい場合は、IPythonを見てみませんか?言語をインタラクティブに学ぶのも良いことです。
  • 多くのテキスト操作を行い、Vimをテキストエディタとして使用する場合、PythonでVimのプラグインを直接作成することもできます。Vimで「:help python」と入力して、指示に従うか、このプレゼンテーションをご覧ください。エディターで直接使用する関数を書くのはとても簡単で強力です!

8
'sh'と呼ばれるipythonプロファイルがあり、インタープリターをシェルに非常に似たものにします。
Autoplectic 2009

3
ipythonの「sh」プロファイルは、しばらくの間削除されています。
gdw2 2013年

>>>結果=!dmesg | grep -i 'usb' #the!オペレーターがすべてを実行
Permafacture 2013年

16

初めに、sh、sed、awk(およびfind、grepなど)がありました。良かったです。しかし、awkは奇妙な小さな獣であり、頻繁に使用しないと覚えにくい場合があります。その後、偉大なラクダがPerlを作成しました。Perlはシステム管理者の夢でした。それはステロイドのシェルスクリプトのようなものでした。正規表現を含むテキスト処理は、言語の一部にすぎませんでした。それからそれは醜くなりました...人々はPerlで大きなアプリケーションを作ろうとしました。さて、誤解しないでください。Perlはアプリケーションになる可能性がありますが、実際に注意しなければ、混乱する可能性があります(可能です!)。次に、このすべてのフラットデータビジネスがあります。プログラマーの頭を動かすのに十分です。

Python、Rubyなどを入力してください。これらは非常に優れた汎用言語です。それらはテキスト処理をサポートし、うまく機能します(ただし、言語の基本的なコアに密接に絡み合っているわけではありません)。しかし、それらも非常によくスケールアップし、結局のところ、見栄えの良いコードが残っています。彼らはまた、ほとんどすべてのもののためのたくさんのライブラリーでかなり多額のコミュニティを開発しました。

さて、Perlに対するネガティブさの多くは意見の問題であり、確かに一部の人々は非常にクリーンなPerlを書くことができますが、この多くの人々は難読化されたコードを作成するのは簡単すぎると不満を持っているので、真実の一部がそこにあることがわかります。質問が実際になって、あなたは単純なbashスクリプトの置き換え以上にこの言語を使用するつもりですか?そうでない場合は、さらに多くのPerlを学習してください。一方、あなたがより多くのことをしたいときにあなたと共に成長する言語が欲しいなら、私はPythonまたはRubyを提案するかもしれません。

いずれにせよ、頑張ってください!




7

Pythonが好きな理由の1つは、POSIXツールよりもはるかに標準化されていることです。各ビットが他のオペレーティングシステムと互換性があることをダブルおよびトリプルチェックする必要があります。Linuxシステムで作成されたプログラムは、OSXのBSDシステムでは同じように機能しない場合があります。Pythonでは、ターゲットシステムに十分に最新のバージョンのPythonがあることを確認するだけです。

さらに良いことに、標準のPythonで記述されたプログラムはWindowsでも実行できます。


1
「標準のPythonで作成されたプログラムはWindowsでも動作します」:冗談ではありませんか?
ジャン=フランソワ・ファーブル

6

ここでは、経験に基づいて私の意見を述べます。

シェルの場合:

  • シェルは非常に簡単に読み取り専用コードを生成できます。それを書きなさい、そしてあなたがそれに戻ってきたとき、あなたはあなたが再びしたことを決して理解しないであろう。これを達成するのは非常に簡単です。
  • シェルは、パイプを使用して1行で大量のテキスト処理、分割などを実行できます。
  • さまざまなプログラミング言語でのプログラムの呼び出しを統合する場合、これは最良の接着剤言語です。

Pythonの場合:

  • 含まれているウィンドウへの移植性が必要な場合は、pythonを使用してください。
  • 数値のコレクションなど、テキストだけではなく操作する必要がある場合は、pythonの方が優れている場合があります。このため、私はpythonをお勧めします。

通常、ほとんどの場合bashを選択しますが、ウィンドウの境界を越える必要がある場合は、Pythonを使用します。



3

私はセミロングシェルスクリプト(300-500行)と同様の機能を実行するPythonコードをビルドしました。多くの外部コマンドが実行されているとき、シェルの方が使いやすいと思います。多くのテキスト操作がある場合、Perlも適切なオプションです。



2

あなたの最善の策は、特にあなたの問題に向けられたツールです。テキストファイルを処理する場合、Sed、Awk、Perlが最有力候補です。Pythonは汎用ダイナミックです言語です。他の汎用言語と同様に、ファイル操作もサポートされていますが、それが核となる目的ではありません。特に動的言語が必要な場合は、PythonまたはRubyを検討します。

要するに、SedとAwkに加えて、* nixのフレーバーに付属しているその他すべての優れた機能(すべてのBash組み込み、grep、trなど)を学んでください。興味のあるテキストファイル処理の場合は、既に適切なものを使用しています。


2

ShellPyライブラリでは、bashの代わりにpythonを使用できます。

GithubからPythonユーザーのアバターをダウンロードする例を次に示します。

import json
import os
import tempfile

# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
    answer_json = json.loads(answer.stdout)
    avatar_url = answer_json['avatar_url']

    destination = os.path.join(tempfile.gettempdir(), 'python.png')

    # execute curl once again, this time to get the image
    result = `curl {avatar_url} > {destination}
    if result:
        # if there were no problems show the file
        p`ls -l {destination}
    else:
        print('Failed to download avatar')

    print('Avatar downloaded')
else:
    print('Failed to access github api')

ご覧のとおり、アクサングラーブ( `)記号内のすべての式はシェルで実行されます。また、Pythonコードでは、この実行の結果をキャプチャして、アクションを実行できます。例えば:

log = `git log --pretty=oneline --grep='Create'

この行は最初git log --pretty=oneline --grep='Create'にシェルで実行され、次にその結果がログ変数に割り当てられます。結果には次のプロパティがあります。

標準出力に実行される処理の標準出力からテキスト全体を

標準エラー出力実行プロセスの標準エラー出力からテキスト全体を

実行のreturncode returncode

これはライブラリの一般的な概要であり、例を含むより詳細な説明はここにあります


1

テキストファイルの操作が通常1回限りで、おそらくシェルプロンプトで行われる場合は、Pythonから何も得られません。

一方、同じ(または同様の)タスクを何度も行う必要があり、それを行うためのスクリプトを作成する必要がある場合は、Pythonが最適です。独自のライブラリを簡単に作成できます(行うことができます)シェルスクリプトでも同じですが、もっと面倒です)。

感触を得るための非常に簡単な例。

import popen2
stdout_text, stdin_text=popen2.popen2("your-shell-command-here")
for line in stdout_text:
  if line.startswith("#"):
    pass
  else
    jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
    # do something with jobID

sysとgetoptモジュールも確認してください。これらが最初に必要になります。


1

PyPI:ezでパッケージを公開しました。インストールに
使用pip install ezします。

シェルには一般的なコマンドがパックされており、私のライブラリは基本的にシェルと同じ構文を使用しています。たとえば、cp(source、destination)はファイルとフォルダの両方を処理できます!(shutil.copyのラッパーshutil.copytreeは、どれを使用するかを決定します)。さらに美しく、Rのようなベクトル化をサポートできます。

別の例:os.walkを使用せず、fls(path、regex)を使用して再帰的にファイルを検索し、正規表現でフィルタリングすると、フルパスの有無にかかわらずファイルのリストが返されます

最後の例:それらを組み合わせて非常に単純なスクリプトを書くことができます:
files = fls('.','py$'); cp(files, myDir)

ぜひチェックしてください!それを書いたり改善したりするのに何百時間も費やしました!


1
おもしろそうですが、私はpypi.python.org/pypi/ezで未フォーマットのドキュメントを突破できません。申し訳ありません...
Greg Dubicki
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.