1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Shell文字列処理メモ(Linux)

Posted at

概要

Linuxで行う文字列処理のメモです。
Ubuntuでなるべくプリインストールされたコマンドを使っています。

行フィルター

パスワード生成

$ pwgen --symbols 12 1
Tu;qu^aey1ue

パスワードを差しさわりのない文字に置き換える

パスワードを差しさわりのない文字に置き換えるか、文字数分のダミー文字列を生成する。

$ echo "Tu;qu^aey1ue" | sed -e 's/./*/g'
************
$ python3 -c "print('*' * 12)"
************
$ ruby -e "puts('*' * 12)"
************

uuidを差しさわりのない文字に置き換える

$ uuidgen 
c2663006-4033-4f6f-bd20-4044eca0ac28
$ uuidgen | tr '[0-9a-f]'
000000000-0000-0000-0000-000000000000

行単位の処理

特定のパターンに一致した行を置換する

printf "Cloudy in Tokyo.\nCloudy in Kyoto.\nCloudy in Osaka.\n" | sed -e '/Tokyo/s/Cloudy/Sunny/'
Sunny in Tokyo.
Cloudy in Kyoto.
Cloudy in Osaka.

特定のパターンに一致した行以外を置換する

printf "Cloudy in Tokyo.\nCloudy in Kyoto.\nCloudy in Osaka.\n" | sed -e '/Tokyo/!s/Cloudy/Sunny/'
Cloudy in Tokyo.
Sunny in Kyoto.
Sunny in Osaka.

特定の行を除外する

BananaDurian を除外する。

  • 入力例

    Apple
    Banana
    Cherry
    Durian
    
  • 出力結果

    Apple
    Cherry
    
  • sed: 行を削除する

    $ printf "Apple\nBanana\nCherry\nDurian\n" | sed -e '/\(Banana\|Durian\)/d'
    Apple
    Cherry
    

    削除したリストを続けて処理できる。

    $ printf "Apple\nBanana\nCherry\nDurian\n" | sed -e '/\(Banana\|Durian\)/d; s/Apple/Apple2/'
    Apple2
    Cherry
    
  • sed: マッチしなかった行を「表示」する

    printf "Apple\nBanana\nCherry\nDurian\n" | sed -ne '/\(Banana\|Durian\)/!p'
    

    「表示」したデータは捨てられるので、続けて置換をしても効果はない。

    $ printf "Apple\nBanana\nCherry\nDurian\n" | sed -ne '/\(Banana\|Durian\)/!p; s/Apple/Apple2/'
    Apple
    Cherry
    
  • Ruby

    printf "Apple\nBanana\nCherry\nDurian\n" | ruby -e "STDIN.each_line(chomp: true){|v| puts v if ! ['Banana', 'Durian'].include?(v)}"
    
  • Python

    printf "Apple\nBanana\nCherry\nDurian\n" | python3 -c "import sys; [print(line) for line in list(filter(lambda x: x not in ['Banana', 'Durian'], [line.rstrip('\n') for line in sys.stdin.readlines()]))]"
    

テキストで行をまたがる処理

行末に空白文字があるファイルを探す

  • 行末に空白文字があるファイルを探す

    grep -nr '[[:blank:]]$' --include='*.rs' .
    
    find . -type f -name '*.rs' -exec egrep -l " +$" {} \;
    

テキストの先頭に行を追加する

  • catを使う
    - は標準入力から読み取ります。そのあと、ファイルから読み取ります。

    #!/bin/bash
    TMP_FILE=$(mktemp $0-XXX.txt) && {
        cat > $TMP_FILE <<EOF
    Cherry
    Durian
    EOF
        printf "Apple\nBanana\n" | cat - $TMP_FILE
        rm -f $TMP_FILE
    }
    
  • sedを使う

    #!/bin/bash
    TMP_FILE=$(mktemp $0-XXX.txt) && {
        cat > $TMP_FILE <<EOF
    Cherry
    Durian
    EOF
        sed -e '1s/^/Apple\nBanana\n/' $TMP_FILE
        rm -f $TMP_FILE
    }
    

マッチした次の行を置換する

パターンの後に {} でブロックをかける。ブロックの中で n が次の行を示す。

  • コード例

    printf "remote:\n  - id: primary\nkey:\n  - id: foo\nacl:\n  - id: update_acl\n" | sed -e '/^key:/{n; s/id: .*/id: UUUUUU/}'
    
  • 入力例

    remote:
      - id: primary
    key:
      - id: foo
    acl:
      - id: update_acl
    
  • 出力例

    remote:
      - id: primary
    key:
      - id: UUUUUU
    acl:
      - id: update_acl
    

テーブル処理

指定の列を取り出す

4列目を取り出す例。

小数点を含む計算、データを振り分けて集計する、など複雑化してきたら、ほかの言語での実装を検討しましょう。
どの環境でも使用できるメリットを考えれば Python が第一候補で、数値計算にも対応しやすいのは利点。
メソッドチェーンでわりと直観かつ簡潔に記述したいなら Ruby でもよい。

  • 入力

    $ ps
        PID TTY          TIME CMD
      79597 pts/10   00:00:00 bash
      89456 pts/10   00:00:00 ps
    
  • Bash配列
    入力データが単純なスペース区切りの場合は、Bash配列のほうが楽(awkの知識を不要とできる)になる場合がある。

    ps | while read LINE; do
        a=($LINE)
        echo "${a[3]}"
    done
    
  • GAWK
    取り出した列そのものが出力結果だったり、区切り文字の指定が必要な場合は GAWK が便利。

    ps | awk '{print $4}'
    
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?