Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sed: getting at the current file name

0 views
Skip to first unread message

Ralf Wildenhues

unread,
Nov 14, 2009, 7:23:01 AM11/14/09
to Paolo Bonzini, bug-gn...@gnu.org
Hi Paolo, bug-gnu-utils,

for operating on several files, GNU sed provides --separate which is
great; but sed is missing a way to get at the file name of the currently
processed file. This would be very convenient for things such as:

# find some bug, transform the found places to a vim quickfix file
for f in $files; do
sed -n "/$pattern_or_complex_script/"' {
=
p
}' $f | sed "N; s/^/$f:/; s/\n/:/"
done > quickfix-file
vim -c 'cf quickfix-file'

where the script is too complex to be emulated by grep, or git grep.

With --separate and a way to print the current file name we could
replace the shell loop with two sed invocations. For example, if a
command `F' would print the file name of the currently open file or `-',
plus a newline, then one could use:

sed -ns "/$pattern_or_complex_script/"' {
F
=
p
}' $files | sed "N; N; s/\n/:/g" > quickfix-file

saving lots of processes.

Alternatively, F could operate on pattern space, say, append the file
name. Not sure if it should prepend a newline in this case.

Would you accept such an extension? Or tell me to use awk?
Currently, the only way I see to do something like this efficiently in
sed is with real weird shell hackery that in-band-signals the file name
into the sed script and also on the command line.

FWIW, this would help for example
<http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/19448/focus=19451>.

Thanks,
Ralf


Ralf Wildenhues

unread,
Nov 15, 2009, 2:24:44 PM11/15/09
to Paolo Bonzini, bug-gn...@gnu.org
* Ralf Wildenhues wrote on Sat, Nov 14, 2009 at 01:23:01PM CET:
> With --separate and a way to print the current file name we could
> replace the shell loop with two sed invocations. For example, if a
> command `F' would print the file name of the currently open file or `-',
> plus a newline, then one could use:
[...]

Proposed patch, still lacking tests. F is a bit unsymmetric to = wrt.
missing --separate, not sure how to change that; take the name of the
first input file only?

Cheers,
Ralf

From 5131e412d337b225f9df3bb49adf62a72d6cf85e Mon Sep 17 00:00:00 2001
From: Ralf Wildenhues <Ralf.Wi...@gmx.de>
Date: Sun, 15 Nov 2009 20:11:21 +0100
Subject: [PATCH] New F command to print input file name

2009-11-15 Ralf Wildenhues <Ralf.Wi...@gmx.de>

* doc/sed.texi (Extended Commands): Document F command.
* doc/sed-in.texi: Regenerate.
* sed/compile.c (compile_program): Accept 'F' if not --posix.
* sed/execute.c (open_next_file): Always initialize in_file_name.
(execute_program): Handle 'F'.
* NEWS: Update.
---
NEWS | 2 ++
doc/sed-in.texi | 7 +++++++
doc/sed.texi | 7 +++++++
sed/compile.c | 3 ++-
sed/execute.c | 18 +++++++++++++-----
5 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index b34758b..085e758 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ Sed 4.2.2

* -u also does unbuffered input, rather than unbuffered output only

+* New command `F' to print current input file name
+
----------------------------------------------------------------------------
Sed 4.2.1

diff --git a/doc/sed-in.texi b/doc/sed-in.texi
index 0e64b23..eb48062 100644
--- a/doc/sed-in.texi
+++ b/doc/sed-in.texi
@@ -1400,6 +1400,13 @@ lines, all but the last ending with a back-slash.
In both cases, the results are undefined if the command to be
executed contains a @sc{nul} character.

+@item F
+@findex F (File name) command
+@cindex Printing file name
+@cindex File name, printing
+Print out the file name of the current input file (with a trailing
+newline).
+
@item L @var{n}
@findex L (fLow paragraphs) command
@cindex Reformat pattern space
diff --git a/doc/sed.texi b/doc/sed.texi
index 66a926e..83d9b8c 100644
--- a/doc/sed.texi
+++ b/doc/sed.texi
@@ -1401,6 +1401,13 @@ lines, all but the last ending with a back-slash.
In both cases, the results are undefined if the command to be
executed contains a @sc{nul} character.

+@item F
+@findex F (File name) command
+@cindex Printing file name
+@cindex File name, printing
+Print out the file name of the current input file (with a trailing
+newline).
+
@item L @var{n}
@findex L (fLow paragraphs) command
@cindex Reformat pattern space
diff --git a/sed/compile.c b/sed/compile.c
index c4a5250..9e9364d 100644
--- a/sed/compile.c
+++ b/sed/compile.c
@@ -1097,7 +1097,7 @@ compile_program(vector)
if (posixicity == POSIXLY_BASIC)
switch (ch)
{
- case 'e': case 'v': case 'z': case 'L':
+ case 'e': case 'F': case 'v': case 'z': case 'L':
case 'Q': case 'T': case 'R': case 'W':
bad_command(ch);

@@ -1230,6 +1230,7 @@ compile_program(vector)
case '=':
case 'd':
case 'D':
+ case 'F':
case 'g':
case 'G':
case 'h':
diff --git a/sed/execute.c b/sed/execute.c
index 28e520d..f9775ea 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -714,6 +714,12 @@ open_next_file(name, input)

input->read_fn = read_file_line;

+ if (follow_symlinks)
+ input->in_file_name = follow_symlink (name);
+ else
+ input->in_file_name = name;
+
+
if (in_place_extension)
{
int input_fd;
@@ -724,11 +730,6 @@ open_next_file(name, input)
memset (&old_fscreatecon, 0, sizeof (old_fscreatecon));
#endif

- if (follow_symlinks)
- input->in_file_name = follow_symlink (name);
- else
- input->in_file_name = name;
-
/* get the base name */
tmpdir = ck_strdup(input->in_file_name);
if ((p = strrchr(tmpdir, '/')))
@@ -1758,6 +1759,13 @@ execute_program(vec, input)
flush_output(output_file.fp);
break;

+ case 'F':
+ output_missing_newline(&output_file);
+ fprintf(output_file.fp, "%s\n",
+ input->in_file_name);
+ flush_output(output_file.fp);
+ break;
+
default:
panic("INTERNAL ERROR: Bad cmd %c", cur_cmd->cmd);
}
--
1.6.5.1.31.gad12b

0 new messages