MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
filter_file.inc
1 # ==== Purpose ====
2 #
3 # Read the contents of a file, filter it through a perl script, and
4 # write it back.
5 #
6 # This is useful in conjunction with include/write_result_to_file.inc
7 # and cat_file or include/read_file_to_var.inc. See
8 # e.g. include/show_events.inc for an example.
9 #
10 # ==== Usage ====
11 #
12 # --let $input_file= <FILE_NAME>
13 # [--let $output_file= <FILE_NAME>]
14 # --let $script= <PERL_SCRIPT>
15 # [--let $select_columns= <LIST OF NUMBERS>]
16 # [--let $pre_script= <PERL_SCRIPT>]
17 # [--let $rpl_debug= 1]
18 # --source include/filter_file.inc
19 #
20 # Parameters:
21 #
22 # $input_file
23 # File to read from.
24 #
25 # $output_file
26 # File to write to. If omitted, writes to $input_file.
27 #
28 # $script
29 # This script will be executed once for each line in $input_file.
30 #
31 # When the script starts, the perl variable $_ will be set to the
32 # current row (including the terminating newline). The script can
33 # modify $_ in any way it likes, and the result will be appended
34 # to $output_file. It is even possible to remove a row by setting
35 # $_ to '', or to generate extra rows by appending "\n" to $_.
36 #
37 # Since mysqltest is incapable of properly escaping dollar
38 # characters, you have to replace any '$' in your script by
39 # 'DOLLAR' (otherwise mysqltest would try to interpolate parts of
40 # your script). filter_file.inc will replace 'DOLLAR' by '$'
41 # before evaluating your script.
42 #
43 # $select_columns
44 # For convenience, if you set this to a space-separated list of
45 # numbers, it will print only the numbered columns, in the given
46 # order.
47 #
48 # $pre_script
49 # This script will be evaluated before starting to iterate over
50 # the lines of $input_file. It can be useful if you need some
51 # sort of initialization; for example, you can define a subroutine
52 # here and call it from $script.
53 #
54 # $rpl_debug
55 # If set, verbose debug info is printed.
56 
57 --let $include_filename= filter_file.inc
58 --source include/begin_include_file.inc
59 
60 if ($rpl_debug)
61 {
62  --echo pre_script='$pre_script'
63  --echo script='$script'
64  --echo select_columns='$select_columns'
65  --echo input_file='$input_file' output_file='$output_file'
66 }
67 
68 --let _FF_PRE_SCRIPT= $pre_script
69 --let _FF_SCRIPT= $script
70 --let _FF_INPUT_FILE= $input_file
71 --let _FF_OUTPUT_FILE= $output_file
72 --let _FF_SELECT_COLUMNS= $select_columns
73 --let _FF_DEBUG= $rpl_debug
74 if (!$output_file)
75 {
76  --let _FF_OUTPUT_FILE= $input_file
77 }
78 perl;
79  my $pre_script = $ENV{'_FF_PRE_SCRIPT'};
80  $pre_script =~ s/DOLLAR/\$/g;
81  my $script = $ENV{'_FF_SCRIPT'};
82  $script =~ s/DOLLAR/\$/g;
83  my $input_file = $ENV{'_FF_INPUT_FILE'};
84  my $output_file = $ENV{'_FF_OUTPUT_FILE'};
85  my $select_columns = $ENV{'_FF_SELECT_COLUMNS'};
86  my $debug = $ENV{'_FF_DEBUG'};
87  if ($select_columns)
88  {
89  chomp($select_columns);
90  $select_columns =~ s/[, ]+/,/g;
91  $script = '
92  chomp;
93  my @cols = split(/\t/, $_);
94  $_ = join("\t", map { $cols[$_ - 1] } ('.$select_columns.'))."\n";
95  ' . $script;
96  }
97  unless ($keep_quotes)
98  {
99  $pre_script = 'my %unquote = ("n"=>"\n","t"=>"\t","\\\\"=>"\\\\");' . $pre_script;
100  $script .= 's{\\\\(.)}{$unquote{$1}}ge;';
101  }
102  if ($debug)
103  {
104  $script = 'print "BEFORE:\'$_\'";' . $script . 'print "AFTER:\'$_\'";'
105  }
106  # Generate a script (perl is faster if we avoid many calls to eval).
107  my $full_script =
108 '
109  open FILE, "< $input_file" or die "Error opening $input_file: $!";
110  my $filtered_contents = "";
111  my %column_names = ();
112  '.$pre_script.';
113  while (<FILE>)
114  {
115  chomp;
116  s/\015?\012?$//;
117  if (!%column_names)
118  {
119  my $n = 1;
120  %column_names = map { $_ => $n++ } split(/\t/, $_);
121  }
122  else
123  {
124  ' . $script . '
125  }
126 
127  if (length($_) > 0)
128  {
129  $filtered_contents .= $_."\n";
130  }
131  }
132  close FILE or die "Error closing $input_file: $!";
133  open FILE, "> $output_file" or die "Error opening $output_file: $!";
134  binmode FILE;
135  print FILE $filtered_contents or die "Error writing filtered contents to $output_file: $!";
136  close FILE or die "Error closing $output_file: $!";
137  return 0;
138 ';
139  if ($debug)
140  {
141  print STDOUT "full_script=<<END_OF_SCRIPT\n${full_script}END_OF_SCRIPT\n"
142  }
143  my $eval_ret = eval($full_script);
144  defined($eval_ret) or die "Parse error or 'die' invoked when evaluating perl script '$full_script': $@";
145  $eval_ret == 0 or die "Non-zero exit value $eval_ret from script '$script'";
146 EOF
147 
148 --let $include_filename= filter_file.inc
149 --source include/end_include_file.inc