67261


Google Colaboratory の `!` 記法で変数と文字列を連結する方法を教えてください。  
また、不可解な挙動もあり、文法を知りたく思っています。  
Python初心者ですが、Linuxのコマンドラインは使用経験があります。

以下はGoogle Colaboratoryで試行錯誤した例です。

**実行したコード**

[code]

    fc="test.txt"
    !echo $fc
    !echo "$fc".bak
    !echo ${fc}.bak
    !echo {fc}.bak
    
[/code]

**結果**

[code]

    test.txt
    test.txt.bak
    .txt.bak
    test.txt.bak
    
[/code]

**質問**

  1. Google colaboratoryの `!` 記法で変数と文字列を連結する正しい方法は  
「3行目」と「5行目」のどちらでしょうか？またはその他でしょうか？

  2. 4行目の書き方で、"test"が消える理由は何ですか？ Pythonの文法で"$"の意味を調べようと  
しましたが、正規表現における"$"の意味しか見つかりませんでした。

$変数名を試した理由は、以下のページなどで$変数名とするとあったからです。

[JupyterやColabのマジックコマンドに対してセル内で定義した変数を引数として与える -
Qiita](https://qiita.com/Hyperion13fleet/items/8951e9ea4ad06764bdad)

ここで自分はLinuxと同じやり方として、連結のために"{}"で囲む方法を試しました。  
また最後の行で$なしも試しました。  
よろしくお願いします。


CC BY-SA 4.0
2020-06-03T10:44:56.890
67258
2020-06-03T16:35:51.503
2020-06-03T16:35:51.503
3060
40461
question
python linux google-colaboratory
Google Colaboratory の ! 記法で変数と文字列を連結する方法


## 変数展開

Google Colaboratory では Jupyter Notebook の IPython カーネルを使っており、変数展開も IPython
に準じた挙動をします。このため、[IPython
のドキュメント](https://ipython.readthedocs.io/en/stable/interactive/python-ipython-
diff.html#shell-assignment)などを調べると良いです。

まず `!` を先頭に付ける形のシェル実行では、使える変数が 2 種類あることに注意してください。ひとつは Python
の変数、もうひとつはシェルで使える変数（たとえば環境変数）です。

`$name` や `{name}` を使うと Python
の変数を展開することができます。更に後者では変数に限らず一般の式を入れられます。シェルの変数を展開するには `$` を `$$` でエスケープします。

以下実行例です。

[code]

    # これは Python の変数
    foo = 42
    !echo $foo
    !echo {foo}
    !echo {foo + 1}
    
    # これは環境変数
    !echo $$PATH
    
[/code]

[code]

    42
    42
    43
    /usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/tools/node/bin:/tools/google-cloud-sdk/bin:/opt/bin
    
[/code]

## 文字列結合

Python の変数を使う場合、Python
の変数が展開された後にシェルスクリプトがシェルに解釈されることに注意しつつ書けば良いです。エッジケースまで考えると面倒くさいので、Python
の側で文字列を結合してしまうのが個人的には好みです。

例1

[code]

    fc = "test.txt"
    !echo '{fc + '.bak'}'
    
[/code]

例2

[code]

    fc = "test.txt"
    backup_filename = f"{fc}.bak"
    !echo '{backup_filename}'
    
[/code]

Python の変数が展開された後にスペースやクォートなどが入ってシェルによるパースに影響しないかに注意してください。

## 質問文の例

最後に補足として、質問文にある 4 つの例がどのように解釈されていたかを説明します。

[code]

    # これは Python の変数。
    fc = "test.txt"
    
    # $name 形式で Python の変数を展開しています。
    !echo $fc
    
    # $name 形式で Python の変数を展開しています。シェルには "test.txt".bak という文字列が渡り、シェルでは全て文字列なのでそのまま結合されます。
    !echo "$fc".bak
    
    # {name} 形式で Python の変数が展開された後、$name 形式でシェルの変数が展開されていると思われます。
    # 今回の場合、まず $test.txt.bak がシェルに渡り、シェル側では $test は空文字列なので .txt.bak になります。
    # このことはたとえば fc = "PATH.txt" とすると確かめられます。
    !echo ${fc}.bak
    
    # {name} 形式で Python の変数を展開しています。
    !echo {fc}.bak
    
[/code]


CC BY-SA 4.0
2020-06-03T14:52:14.320
67261
2020-06-03T16:27:14.643
2020-06-03T16:27:14.643
19110
19110
67258
answer