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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Linux

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

sh

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

Q&A

解決済

4回答

13083閲覧

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

DAIKAN

総合スコア13

Linux

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

sh

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

0グッド

0クリップ

投稿2017/03/07 08:36

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

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

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

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

bash

1TARGET_MSG_ID="" 2SEPARATOR="" 3while read line 4do 5 TARGET_MSG_ID="${TARGET_MSG_ID}${SEPARATOR}${line}" 6 if [ "${SEPARATOR}" = "" ] 7 SEPARATOR="," 8 fi 9done

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

投稿2017/03/07 09:27

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

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

投稿2017/03/07 09:00

A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2017/03/07 14:11

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

2017/03/07 14:18

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

2017/03/07 14:30

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

2017/03/07 15:01

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

2017/03/08 00:30

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

0

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

Bash

1TARGET_MSG_ID= 2last= 3while read line 4do if test -n "$last" 5 then TARGET_MSG_ID="$TARGET_MSG_ID$last," #最後以外の処理 6 fi 7 last="$line" 8done < msg_id.txt 9TARGET_MSG_ID="$TARGET_MSG_ID$last" #最後の処理 10 11echo "$TARGET_MSG_ID"

投稿2017/03/07 14:15

編集2017/03/07 14:18
otn

総合スコア84555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DAIKAN

2017/03/08 00:29

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

0

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

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

sh

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

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

投稿2017/03/07 09:25

manzyun

総合スコア2244

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2017/03/07 10:33

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問