リストを特定のキャラクターに合わせる方法は?


13

テキストの行を任意の文字に水平方向に揃えるために使用できるコマンドまたはコマンドのセットはありますか?たとえば、電子メールアドレスのリストを使用すると、すべての「@」文字が縦に並んだテキストファイルが出力されます。

成功するには、ほとんどの行の先頭に可変数の空のスペースを追加する必要があると思います。読み取りに多くの労力がかかるため、別々の列は必要ありません(たとえばcolumn -t -s "@" < file.txt)。

前:

123@example.com
456789@example.net
01234@something-else.com

後:

   123@example.com
456789@example.net
 01234@something-else.com

別の言い方をすると、文字をアンカーポイントとして指定できますか?これの私のユースケースは、視覚的にスキャンしやすくするためのメールアドレスです。


1
複数の@シンボルがある場合はどうなりますか?
ゼータ

良い質問です。複数の@記号は電子メールアドレスの問題ではありませんが、ユーザーは行ごとに文字のインスタンスを選択して、他のテキストの中心となる「アンカー」にする必要があります。
トムブロスマン

1
@電子メールアドレスには複数の記号を使用できますtom"@brossmann"@example.com。それが、複数の@シンボルがある場合に何が起こるかを尋ねた理由です:)。
ゼータ

@Zeta複数の@シンボルは、さまざまなメールサービスで許可されていません。生のフィルタリングされていないユーザー入力を処理する場合を除き、「実際の」メールよりも厳しい標準に適合する「通常の」メールを期待することは完全に合理的です@
ファンドモニカの訴訟

回答:


3

いいえ のみsedcolumn

column -ts@ file.txt | sed -E 's/([^ ]+)([ ]+) (.+)/\2\1@\3/'

出力:

   123@example.com
456789@example.net
 01234@something-else.com

さて、私が考えると、これはSundeepのソリューションとほとんど同じで、短く見える/への呼び出しが少ないだけでなく、各行で1回だけ発生するsedことも想定してい@ます。


1
それも、より短くすることができます:column -ts@ input.txt | sed -r 's/([^ ]+)( *)\s\s/\2\1@/'
MiniMaxの

11

最も単純な場合、適切な大きなフィールド幅で最初のフィールドを印刷することができます。例えば

awk -F@ 'BEGIN{OFS=FS} {$1 = sprintf("%12s", $1)} 1' file
         123@example.com
      456789@example.net
       01234@something-else.com

特定の最大フィールド幅を想定していないメソッドでは、ファイルをメモリに保持するか、2つのパスを作成する必要があります。


1も使用することができます長得るための良い1、cw=$(cut -d@ -f1 file | wc -L)その後、awk -v w="$cw" 'BEGIN{OFS=FS="@"} {$1 = sprintf("%*s", w, $1)} 1'
Sundeep

328個のアドレスのリストに対してこれをテストすると、10個が何らかの形で出力から欠落しています(現在318行)。明確にするために、私は走ったawk -F@ '{a[$1] = $2; w = length($1) > w? length($1) : w; next} END {for (i in a) printf("%*s%c%s\n", w, i, FS, a[i])}' INPUT-FILE.txt > OUT.txt。残りはうまくフォーマットされましたが、一部のデータが欠落しています。
トムブロスマン

1
@TomBrossmanおかげで、私はちょうどそれは非常に重大な欠陥を持って実現-それは同じ名前のフィールドを処理しません-私は1削除するつもりだ
steeldriver

より簡潔に、同じ結果が、awk -F@ '{printf "%12s@%s\n", $1, $2}' input.txt
MiniMaxの

6

ハッキングソリューション、入力テキストについて多くのことを想定

$ # four commas to reduce chance of it affecting actual email address
$ sed 's/@/,,,,@/' ip.txt | column -t -s,,,,
123     @example.com
456789  @example.net
01234   @something-else.com

$ sed 's/@/,,,,@/' ip.txt | column -t -s,,,, | sed -E 's/^([^ ]+)( +)/\2\1/'
     123@example.com
  456789@example.net
   01234@something-else.com

4

セパレーターの左にあるすべての文字列を右揃えする、可能な限り短いパディング長を使用する簡単なPythonソリューション:

#!/usr/bin/env python3
import sys
fieldsep = '@'
records = [line.rstrip('\n').split(fieldsep, 1) for line in sys.stdin]
col1_len = max((len(r[0]) for r in records), default=0)
for r in records:
    print(r[0].rjust(col1_len), r[1], sep=fieldsep)

使用法:

python3 align-field.py < data.txt

2

別のGNU awk+ columnソリューション:

awk '{ split($0,a,/ +/,sep); printf "%*s@%s\n",length($1 sep[1])-2,$1,$2 }' <(column -ts'@' file)

出力:

   123@example.com
456789@example.net
 01234@something-else.com

これがどのように機能するかについて少し追加していただけますか?
ジョー

2

これは、Bash文字列操作でも機能します。

Bashスクリプト(4.x):

#!/bin/bash

read -d '' -r -a data <"data.txt"

for ((pos=0, i=0; i<${#data[@]}; i++)); do
    locl=${data[$i]%@*}                         # The local-part.
    [[ ${#locl} -gt $pos ]] && pos=${#locl}     # Determine the lengthiest $locl.
done

for ((i=0; i<${#data[@]}; i++)); do
    email=${data[$i]}
    locl=${email%@*}                            # The local-part.
    domain=${email#*@}                          # The email domain.
    printf '%*s@%s\n' $pos $locl $domain        # Align $locl to the right, at $pos.
done

結果:

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