'tr'のみを使用して複数のスペースを1つに置き換えます


71

私はファイルを持っていますf1.txt

ID     Name
1      a
2         b
3   g
6            f

スペースの数は固定されていません。のみを使用してすべての空白を1つのスペースに置き換える最良の方法は何trですか?

これは私がこれまでに持っているものです:

cat f1.txt | tr -d " "

しかし、出力は次のとおりです。

IDName
1a
2b
3g
6f

しかし、私はそれがこのように見えることを望みます:

ID Name
1 a
2 b
3 g
6 f

試してみてくださいsed


6
なぜsedを避けることが重要なのですか?どんなものでも使用してください!
デビッドリチャービー14

7
私がそれをする方法を知っているからですsed。他の方法を知りたい:)
gkmohit 14

回答:


106

trsqueeze repeatオプションを使用します。

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

または、awkソリューションを使用できます:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

レコード内のフィールドを変更すると、awkrebuild $0がすべてのフィールドを取得しOFS、デフォルトでスペースであるで区切られたフィールドを連結します。

これにより、スペースとタブのシーケンス(およびロケールと実装に応じて他の空白文字awk)が1つのスペースに詰め込まれますが、各行の先頭と末尾の空白も削除されます。


1
これも素晴らしい解決策です。。。私は今どれを選ぶべきかわからない:/ @Gnouc
gkmohit 14

好きなソリューションを自由に選んでください。私の解決策は@polymの答えとは異なることに注意してください。
cuonglm

1
:)) わーい!@Gnoucの答えは本当に動的awkです。彼はを使用しているため、何でもできます。彼の解決策を受け入れることもできます。ただ一つ:Gnoucは、コマンドのawk形式が何をするのか説明できるでしょうか?また、タブ/スペースを追加して、出力がUnknownの予期される出力に適合するようにすることはできますか?
polym 14

1
@polym:Unknownの最後の編集では、彼はスペースが1つだけ欲しいようで、出力はcolumn -tそうではありません。の説明を追加しawkます。
クオングルム14

4
ここには小さな違いがあります。tr行末の2つのスペースを単一のスペースに置き換えます。awk末尾のスペースをすべて削除します。
アンヴァンロッサム

19

ただ使用するcolumn

column -t inputFile

出力:

ID  Name
1   a
2   b
3   g
6   f


1
@Unknown素晴らしいサービス:)!
polym 14

1
@Gnoucはすごい、列も引数としてファイルを取ります。よかった、ありがとう!
polym 14

どうすれば2列目を取得できますか?私が試したcolumn -t f1.txt | cut -d " " -f2 が、私は期待解決策ではありませんでした
gkmohit

2
その後、AWKを使用します。column -t file | awk '{print $2}'唯一の二列を出力します
polym

8

「空白」を絞りたい場合は、trの事前定義文字セット「:blank:」(水平の空白タブとスペース)または「:space:」(垂直空白)を使用します。

/bin/echo -e  "val1\t\tval2   val3" | tr -s "[:blank:]"

例はRed Hat 5(GNU tr)で実行されました。

私の場合、すべての空白を単一のスペースに正規化して、スペースを削除者として使用できるようにしました。

dastrobuの2番目のコメントで指摘したように、manページの言葉遣いを見逃しました。

 -s uses the last specified SET, and occurs after translation or deletion.

これにより、最初のtrを削除できます。工藤は私の密度に直面して彼の忍耐のためにスコットすることです。

前に、Redis構成からポートを解析します。ファイル:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

その後、squeezeでSET2が指定されます:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

出力:

6379

空白のニュアンスをカバーする詳細については

[:blank:]文字クラスに属する連続した混合文字が関係する場合、squeezeだけが失敗することを示します。

 /usr/bin/printf '%s \t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      \t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

注:printf形式の2つの文字列フィールドは、スペース1つ、タブ1つ、スペース1つで区切られています。スクイーズ後、このシーケンスはまだ存在します。Octalダンプの出力では、これはASCIIシーケンス040 011 040で表されます。


1
本当に必要tr "[:blank:]" " " | tr -s "[:blank:]"ですか?最初の部分で十分だと思いtr "[:blank:]" " "ます。つまり、空白を正規化し、すでに置換を行っているからです。manページから:「文字の複数の出現を絞る[...]これは、すべての削除と翻訳が完了した後に発生します。」
-dastrobu

2
そのため、´tr -s "[:blank:]" "" ´は、最初にすべての空白をスペースに変換してからスペースを圧縮します。2番目の「tr」は必要ありません。
-dastrobu

1
printf 'ID \t Name\n' | tr -s "[:blank:]" " " | od -cb(@dastrobuが示唆するように)試したところ、出力としてID Name\n(スペースを1つ)取得しました。@ user3183018を実際に試しましたか?
スコット

1
OK、もう一度言ってみましょう。私はprintf 'ID␣\t␣Name\n' | tr -s "[:blank:]" "␣"  (@dastrobuが示唆するように)スペースを表し、ID␣Name\n出力として(スペースを1つ)取得しました。これは、「Port <SPACE> <TAB> <SPACE> 6379」のとまったく同じですが、質問の見出し文字列を使用しました。tr -s "[:blank:]"(最後の"␣"引数なしで)試したかどうか疑問に思っています  。
スコット

1
私がやるとprintf 'ID \t Name\n' | od -cb、それが何をすべきかを正確に示します:(ID ⁠  \t ⁠  N a m e \nつまり  ID 040 011 040 N a m e\n)。一方、あなた自身の証拠により、あなたは私が推測した正確なエラーを犯しています:@dastrobuと私が今4回提示したコマンドの代わりに、あなたは走っていますtr -s "[:blank:]"(すなわち、  tr1つのオプションと  1つの引数で):tr -s '[:blank:]' '␣'(つまり、  tr1つのオプションと  2つの引数を使用)。
スコット

5

(シェル以外の)プログラムが必要なのは誰ですか?

while read a b
do
    echo "$a $b"
done < f1.txt

polymのcolumn答えのように、2番目の列の値を揃えたい場合は、printf代わりにを使用しますecho

while read a b
do
    printf '%-2s %s\n' "$a" "$b"
done < f1.txt

1
そもそもtrと比較すると、これは、入力が小さすぎてtr呼び出しのわずかなコストを上回らない限り、効率的には非常に弱い提案です-書くのにどれだけの作業が必要かは言うまでもありません。最後に、この投稿は質問に実際に答えていないとは言いませんか?trのみを使用して、すべての空白を1つのスペースに置き換える最良の方法は何ですか?
mikeserv 14

1
それに加えて-あなたはもっと簡単に何かをすることができなかったのです$IFSか たぶん次のようにIFS=' <tab>' set -f ; echo $(cat <file)
mikeserv 14

2

これは古い質問であり、何度も解決されました。完全を期すために:似たような問題がありましたが、パイプを介して他のプログラムにラインを渡したいと思いました。xargsを使用しました。

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

そのcat f1.txt | xargs -L1正確に何をしたい出力に思えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.