正規表現の結果に基づいてファイルをソートしたいと思います。たとえば、Obj-Cに次の属性宣言がある場合
@property (nonatomic, strong) id <AlbumArtDelegate, UITextFieldDelegate> *albumArtView; // 1
@property (nonatomic, strong, readonly) UIImageView *profileView; // 2
@property (nonatomic, strong, readwrite) UIButton *postFB; // 3
@property (nonatomic, assign) UIButton *saveButton; // 4
基本的には[4, 1, 2, 3]の順にソートされますが、実際の属性名である[1, 3, 2, 4]の順にソートしたいと思います。属性名だけを調べる正規表現を作成でき、その式の結果に基づいてソートできますか?
これを行うための組み込みのUnixツールはありますか?私はXcodeで作業しているので、VIM / emacsソリューションは役に立ちません。
また、正規表現を使用してこれを実行したいのは、他の状況でも機能するようにソートアルゴリズムを拡張できるためです。メソッド宣言、import文などをソートするために使用します。
答え1
行内容の機能に基づいてソートする一般的な方法は次のとおりです。
- ソートするキーを取得し、行の先頭にコピーします。
- タイプ
- 行の先頭のキーの削除
この特別なケースでは、次のキーを使用できます。プログラムはsed
最後の識別子から最後まで行を出力します。
% sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls
albumArtView; // 1
profileView; // 2
postFB; // 3
saveButton; // 4
これらのキーを元の行と並べて配置するには、次の手順を実行します。
% paste <(sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls) decls
並べ替え...
| sort
2番目のフィールド(元の行)のみを保持します。
| cut -f 2-
すべてを整理すると(表示する内容があるように逆順に並べ替え):
% paste <(sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls) decls \
| sort -r \
| cut -f 2-
→
@property (nonatomic, assign) UIButton *saveButton; // 4
@property (nonatomic, strong, readonly) UIImageView *profileView; // 2
@property (nonatomic, strong, readwrite) UIButton *postFB; // 3
@property (nonatomic, strong) id <AlbumArtDelegate, UITextFieldDelegate> *albumArtView; // 1
答え2
PIPED-DATA | sed -r "s/(\*\w+)/\x01&\x01/" | sort -k2 -t$'\x01' |tr -d $'\x01'
あなたの場合は、上記のスクリプトで十分です。実際、デフォルトでは、単一のキーフィールドのソートには十分です。同じスクリプトの場合は展開して読み続けます。
次のスクリプトは、ソートするフィールドを設定します。2しかし、場所のレイアウトは非常に柔軟です。必要に応じて適切な正規表現パターンを指定し、それに応じてソートオプションを変更して複数のフィールドをソートできます。
(
各フィールドパターンは通常の角かっこで)
囲む必要があります'single-quoted'
。
あなたが提供するパターンは、あなたが選択した一意の文字として定義されます。 sed
独自の区切り文字も必要です。スクリプトは区切り文字\x01
と\x02
。これらの区切り記号の値は通常、テキストファイルに表示されないために選択されました。
フィールド区切り文字ではなく、フィールドの組み合わせに基づいて設定を考慮する必要があります。
n=2 # field number to sort on
p=( '(.*)' '(\*\w+)' '(.*)' ) # Set up regex field patterns
f=; r=; d=$'\x01'; x=$'\x02' # Build patterns and delimiters
for (( i=0; i<${#p[@]}; i++ )) ;do
f+="${p[i]}"; r+="\\$((i+1))$x"
done
sed -r "s$d$f$d$r$d" file |sort -k$n -t"$x" |tr -d "$x"
出力:
@property (nonatomic, strong) id <AlbumArtDelegate, UITextFieldDelegate> *albumArtView; // 1
@property (nonatomic, strong, readwrite) UIButton *postFB; // 3
@property (nonatomic, strong, readonly) UIImageView *profileView; // 2
@property (nonatomic, assign) UIButton *saveButton; // 4
答え3
sort -k 5 ~/Temp/data
Cygwinで私に効果的です。
答え4
私は最初のキャプチャに基づいてファイルをソートするために正規表現を入力できるPerlスクリプトを作成しました。その後、文字列または数値比較を実行するようにフラグを設定できます。このコード例を.plファイルに入れます。
とても簡単です。ロジックは20〜37行にあります。
#! /usr/bin/perl
# Created by pete Nixon
use Getopt::Long;
use strict;
use Cwd qw(abs_path);
my $exec_path = abs_path($0);
$exec_path =~ s/(.*\x2f)[^\x2f]+$/$1/g;
my $path = abs_path($1);
&getCommandLineArguments;
my $file_flag;
my $regex;
my $type_flag;
my @lines;
my @sortedLines;
open (FILE, $file_flag) || die "Couldn't open rule file, $!";
while (<FILE>) {
chomp $_;
if ($_ =~ /^\s*\n/) {
next;
}
push (@lines, $_);
}
if ($type_flag eq 1) {
@sortedLines = sort { ($a =~ m/$regex/)[0] <=> ($b =~ m/$regex/)[0]} @lines; # where the magic happens
} else {
@sortedLines = sort { ($a =~ m/$regex/)[0] cmp ($b =~ m/$regex/)[0]} @lines; # where the magic happens
}
foreach (@sortedLines) {
print "$_\n";
}
sub getCommandLineArguments() {
my $help;
my $clear = "[0m";
my $black = "[0;30m";
my $blue = "[0;34m";
my $green = "[0;32m";
my $cyan = "[0;36m";
my $red = "[0;31m";
my $purple = "[0;35m";
my $brown = "[0;33m";
my $gray = "[0;37m";
my $darkGray = "[1;30m";
my $lightBlue = "[1;34m";
my $lightGreen = "[1;32m";
my $lightCyan = "[1;36m";
my $lightRed = "[1;31m";
my $lightPurple = "[1;35m";
my $yellow = "[1;33m";
my $white = "[1;37m";
GetOptions (
'file|f=s' => \$file_flag,
'regex|r=s' => \$regex,
'type|t=s' => \$type_flag,
'help|h|?' => \$help
) or die ("Error in command line arguments$clear\n");
if ($help || $file_flag eq undef && $regex eq undef) {
print "$green================================================================================$clear\n";
print "$red WHAT DOES THIS SCRIPT DO?\n$clear";
print "$cyan - This program a regex and sorts a line based on it.\n$clear";
print "$red HOW DO I USE THIS SCRIPT?\n$clear";
print "$cyan - Type the name of this script, space, options (see the next section)\n$clear";
print "$green SAMPLE: '$clear" . "sortbyregex.pl -f file -r \"regex\" -t (1|2)$green'\n$clear";
print "$red WHAT OPTIONS ARE AVAILABLE?\n$clear";
print "$yellow -f, --file\n$clear";
print "$cyan - Use to specify a regex\n$clear";
print "$yellow -r, --regex\n$clear";
print "$cyan - Use to specify the regex used for sorting, must include one capture\n$clear";
print "$yellow -t, --type\n$clear";
print "$cyan - Use to specify the type of sorting 1 = numeric 2 = string\n$clear";
print "$yellow -h, --help, -?\n$clear";
print "$cyan - Use to see this help... so... yeah...\n$clear";
print "$green================================================================================$clear\n";
exit(0);
}
}