質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • Linux

    4051questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • sh

    298questions

    shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。

シェルスクリプトのread lineにおいて、最終行だけ処理を変える方法

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 2,760

DAIKAN

score 5

read lineにおいて、最終行だけ処理を変える方法をご教授下さい。

下記の通り、各行に数値が羅列されている
msg_id.txtがあります。

1
2

10

msg_id.txtの各行をカンマ(,)で結合した文字列:TARGET_MSG_IDを作りたいです。

下記のような処理では、1,2,…,10,となってしまいますが、
1,2,…,10と、文字列の最後にはカンマがつかないようにしたいです。

while分の中で、最終行だけ処理内容を変えるような
記述は出来るのでしょうか。

========================================
TARGET_MSG_ID=""
while read line
do
TARGET_MSG_ID="$TARGET_MSG_ID${line},"

done < msg_id.txt

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+6

readline は「今が最終行である」ことを検知できません。検知できるのは「もう取る行がない」だけです。
ですから最終行を判定するようなことをしようとしてはいけません。

, がついてほしくないならば、逆に考えて

  • 最初に読み込んだ行ならばそのまま
  • それ以外なら、',' を付けてから読み込んだ内容を付け加える

でもいいのです。
なのでこういう手が使えます。

TARGET_MSG_ID=""
SEPARATOR=""
while read line
do
  TARGET_MSG_ID="${TARGET_MSG_ID}${SEPARATOR}${line}" 
  if [ "${SEPARATOR}" = "" ]
    SEPARATOR=","
  fi
done


最初の行のときは SEPARATOR が "" ですから、何もつきません。
その直後の if 文で SEPARATOR が "," に変更されるので、2行目では [1行目の内容],${line} とくっつくようになります。 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+3

最後にカンマを削るのは?
TARGET_MSG_ID=${TARGET_MSG_ID:0:${#TARGET_MSG_ID}-1}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/07 23:11

    TARGET_MSG_ID=${TARGET_MSG_ID%,}
    で良いです。

    キャンセル

  • 2017/03/07 23:18

    さすがですね。/でないので思い出せませんでした。

    キャンセル

  • 2017/03/07 23:30

    # と % で、どっちがどっちか覚えにくかったのですが、キーボードの左の方にある # が先頭の削除、右の方にある % が末尾の削除ということで覚えました。

    キャンセル

  • 2017/03/08 00:01

    ありがとうございます、いつもその度にechoしてました。頂きます。

    キャンセル

  • 2017/03/08 09:30

    迅速はご回答ありがとうございました。
    ひとまずは、ループ処理終了後にTARGET_MSG_ID=${TARGET_MSG_ID%,}とすることで、
    対応するようにしようと思います。

    キャンセル

+1

「各行をカンマで繋ぐ」であれば、t_obaraさんの paste -s で十分ですが、
「最終行だけ別の処理をしたい」の一般化された場合にも出来るように考えてみました。
ループで一回ずつ遅らせて処理します。

TARGET_MSG_ID=
last=
while read line
do if test -n "$last"
   then TARGET_MSG_ID="$TARGET_MSG_ID$last," #最後以外の処理
   fi
   last="$line"
done < msg_id.txt
TARGET_MSG_ID="$TARGET_MSG_ID$last" #最後の処理

echo "$TARGET_MSG_ID"

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/08 09:29

    ありがとうございます!
    「最終行だけ別の処理をしたい」の、一般化された考えも知りたかったため、大変助かりました。

    キャンセル

0

パッと思いつく方法としては、全部","をつけてしまった後に、最後の行だけ","を抜く。という方法でしょうか。

しかし、個人的にはcatとsedでワンラインでなんとかできちゃうんじゃないかと勝手に思ってしまうのですが、やっぱりダメですかね。

cat msg_id.txt | sed -e s/([0-9]+)\$/\1,/g | sed -e s/,\$//g > done.txt

こんな感じでどうでしょう。間違っていたら申し訳ございません。バックアップを取ってから実行して見てください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/07 19:33

    > ワンラインでなんとか
    確かに。
    この場合に限っては、pasteコマンドで一発っぽいです。
    paste -s -d ',' msg_id.txt > new_msg_id.txt
    * あまりサイズが大きいと怒られそうですけど。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Linux

    4051questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • sh

    298questions

    shは、UNIX系OSのシェル操作の1つであり、最も基本的なシェルのことです。