[augeas-devel] Unique numbered labels in indexes

David Lutterkort lutter at redhat.com
Tue Jun 16 18:37:02 UTC 2009


On Tue, 2009-06-16 at 13:20 +1000, Matt Palmer wrote:
> A few days ago David wrote:
> 
> > The best way to get unique labels when Augeas autgenerates numbered
> > labels (i.e., uses 'seq' in the lens) is to use labels that start with
> > '0', i.e. '01', '02' etc.
> 
> As lovely as that is, what about all those times when I'm dealing with an
> entry that *doesn't* use seq (such as the sudoers lens)?  I just tried the
> zero-padding:
> 
> set /files/etc/sudoers/spec[01]/user root
> [...]
> 
> And overwrote an existing entry (specifically, .../spec[1]).  D'oh!  So, am
> I going back to 100000, or is there a separate magic trick for indexes?

Those two '01's mean very different things: the labels of tree nodes are
strings, no exceptions. So when you have something
like /files/etc/hosts/01, that last '01' is a string.

In predicates in path expressions, something like /foo/bar[01] is
shorthand for /foo/bar[position() = 01] (just as in XPath) and 01 is
interpreted as a number, and will therefore match the first 'bar' child
of any 'foo' node.

The grammar for path expressions is ambiguous at the point where the
'01' in something like /foo/bar[01] is parsed, since the '01' can either
be parsed as the name of a node or as a number. The parser resolves that
ambiguity by always parsing that as a number.

If you want to make it clear that you want the '01' to be taken as the
name of a node, you'd have to write /foo/bar[child::01] - that matches
'bar' nodes that have a child labelled '01'. To clarify this some more,
here's an example:

        augtool> set /test/foo[1] 'Foo 1'
        augtool> set /test/foo[2] 'Foo 2'
        augtool> set /test/foo[1]/bar bar
        augtool> set /test/foo[2]/01 01
        augtool> print /test
        /test
        /test/foo[1] = "Foo 1"
        /test/foo[1]/bar = "bar"
        /test/foo[2] = "Foo 2"
        /test/foo[2]/01 = "01"
        augtool> match /test/foo[01]
        /test/foo[1] = Foo 1
        augtool> match /test/foo[child::01]
        /test/foo[2] = Foo 2
        
So, how do you add a new node to a list of nodes that have the same
name ? One way to do that is to use last():

        augtool> set '/files/etc/hosts/1/alias[last() + 1]' newhost.example.com

The more explicit way would be to do

        augtool> ins alias after /files/etc/hosts/1/alias[last()]
        augtool> set /files/etc/hosts/1/alias[last()] newhost.example.com

David





More information about the augeas-devel mailing list