I have created in /etc/systemd/system the following service - my test.service , however when I try to start the service via systemctl start "my test.service" the service does not get started and it is not found.How can I escape the name of the service if it contains spaces?
Valid unit names consist of a "name prefix" and a dot and a suffix specifying the unit type. The "unit prefix" must consist of one or more valid characters (ASCII letters, digits, ":", "-", "_", ".", and ""). The total length of the unit name including the suffix must not exceed 256 characters. The type suffix must be one of ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".slice", or ".scope".
Source (noted by JayEye): https://www.freedesktop.org/software/systemd/man/systemd.unit.html
You can't. systemd.unit(5) clearly states what characters are allowed in unit names.
Related
I am working on the EBS configuration side of the SAP ERP system where I am trying to define Search Strings for the MT940 format (as per SAP SPRO activity "Define Search String for Electronic Bank Statement", for instance see this blog post).
I am trying to create a search pattern that is able to identify special characters in the MT940 format, for example ?/!/>, etc.
My search pattern: \C*######\C*
The text that I use to identify the mapping:
:86:306?00CCY RECD?20/BI/**?651234?**/BO/DE652004ED
In this case, I defined:
\C* as to look for special characters - this will be skipped based on the mapping.
# to look for a sequence of 6 numbers.
My results from the test:
1 651234
2 652004
3 651234
4 652004
The result I look to achieve based on the search pattern defined: 651234
I do understand that the reason for having the repetition is because of the * symbol. However, if I skip adding that symbol, the search pattern will end up in error.
My problem is that I cannot seem to understand how can I translate special characters to be identified by the SAP Search Strings? Furthermore, how can I identify if it is a letter?
Below is the Search String definition from the SAP documentation of SPRO activity "Define Search String for Electronic Bank Statement":
String for searches in text. A search string consists of normal characters (that is, letters and digits) and other characters:
| Or
( ) Grouping
+ Repeats the previous character once or several times
* "Zero" or repeats the previous character several times
? Any individual character you want
# Any of the digits 0 to 9
^ Start of a line
$ End of a line
\ Escape symbol
Examples:
The search string "ab" fits each position in a character string in which the letter "b" follows the letter "a".
The search string "(A+|B)+C" "AC", "BC", "AAAAAC" or "ABAAC".
"(A+|B+)C fits "AC", "BC" and "AAAAAC", but not "ABAAC".
"\*C" fits "*C"; the effect of the escape symbol is that "*" is not interpreted as a special character.
This is the first time I raise a question, therefore, I want to apologize if the format is not correct or the text was too long.
Many thanks for your time and help!
At the moment I am busy with a spreadsheet to analyse results per url. The problem is that when I want to make a list of unique urls the urls with a parameter behind it (for example '?fbads') will be seen as unique, instead of that I need these results to be blended together with the main url. See example below:
https://www.holidayguru.nl/deal/accommodatie/luxe-strandvakantie-in-ijmuiden-5e25ba62-e001-4072-8eb5-b6c3b0e7e66f/?fbclid=IwA
&
https://www.holidayguru.nl/deal/accommodatie/luxe-strandvakantie-in-ijmuiden-5e25ba62-e001-4072-8eb5-b6c3b0e7e66f/
Should both be: https://www.holidayguru.nl/deal/accommodatie/luxe-strandvakantie-in-ijmuiden-5e25ba62-e001-4072-8eb5-b6c3b0e7e66f/
I already fixed this with a formula but I need one list with all urls. So I'm look for two options. Or in the
=LEFT(A11,FIND("?",A11)-1)
That I use right now I need to find a way how I can say. If you don't find a '?' than just copy cell A11
Or...
I have to work with an if fuction to say, if A11 contains '?' than execute =left fuction otherwise use A11.
I can't manage to get the formula working. Demo sheet is down below :). Thanks!
Example spreadsheet
Delete everything from Sheet1!A:A (including the header) and place the following in Sheet1!A1:
=ArrayFormula({"UNIQUE URLS"; UNIQUE(FILTER(REGEXEXTRACT(URLs!A2:A,"[^\?]+"),URLs!A2:A<>""))})
This will create the header (which you can change as you like within the formula itself) and a unique list of URLs as determined only by the portion before a question mark (if a question mark exists) or to the end of the original URL.
For your reference, the expression [^\?]+ means "a string of the greatest length that can be extracted without containing a literal question mark."
[ ] = "any of the characters contained herein"
[^ ] = "not any of these characters"
\ = literal marker (i.e., whatever is next will be treated as a literal character)
\? = literal question mark (using the literal marker before the ? is necessary, since alone, the ? has a separate special meaning in REGEX-type expressions)
+ = "one or more of the preceding character or group of characters"
I have a program written in python3 that should parse several domain names every day and extrapolate data.
Parsed data should serve as input for a search function, for aggregation (statistics and charts) and to save some time to the analyst that uses the program.
Just so you know: I don't really have the time to study machine learning (which seems to be a pretty good solution here), so I chose to start with regex, that I already use.
I already searched the regex documentation inside and outside StackOverflow and worked on the debugger on regex101 and I still haven't found a way to do what I need.
Edit (24/6/2019): I mention machine learning because of the reason I need a complex parser, that is automate things as much as possible. It would be useful for making automatic choices like blacklisting, whitelisting, etc.
The parser should consider a few things:
a maximum number of 126 subdomains plus the TLD
each subdomain must not be longer than 64 characters
each subdomain can contain only alphanumeric characters and the - character
each subdomain must not begin or end with the - character
the TLD must not be longer than 64 characters
the TLD must not contain only digits
but I to go a little deeper:
the first string can (optionally) contain a "usage type" like cpanel., mail., webdisk., autodiscover. and so on... (or maybe a symple www.)
the TLD can (optionally) contain a particle like .co, .gov, .edu and so on (.co.uk for example)
the final part of the TLD is not really checked against any list of ccTLD/gTLDs right now and I don't think it will be in the future
What I thought useful to solve the problem is a regex group for the optional usage type, one for each subdomain and one for the TLD (the optional particle must be inside the TLD group)
With these rules in mind I came up with a solution:
^(?P<USAGE>autodiscover|correo|cpanel|ftp|mail|new|server|webdisk|webhost|webmail[\d]?|wiki|www[\d]?\.)?([a-z\d][a-z\d\-]{0,62}[a-z\d])?((\.[a-z\d][a-z\d\-]{0,62}[a-z\d]){0,124}?(?P<TLD>(\.co|\.com|\.edu|\.net|\.org|\.gov)?\.(?!\d+)[a-z\d]{1,64})$
The above solution doesn't return the expected results
I report here a couple of examples:
A couple of strings to parse
without.further.ado.lets.travel.the.forest.com
www.without.further.ado.lets.travel.the.forest.gov.it
The groups I expect to find
FullMatchwithout.further.ado.lets.travel.the.forest.com
group2without
group3further
group4ado
group5lets
group6travel
group7the
group8forest
groupTLD.com
FullMatchwww.without.further.ado.lets.travel.the.forest.gov.it
groupUSAGEwww.
group2without
group3further
group4ado
group5lets
group6travel
group7the
group8forest
groupTLD.gov.it
The groups I find
FullMatchwithout.further.ado.lets.travel.the.forest.com
group2without
group3.further.ado.lets.travel.the.forest
group4.forest
groupTLD.com
FullMatchwww.without.further.ado.lets.travel.the.forest.gov.it
groupUSAGEwww.
group2without
group3.further.ado.lets.travel.the.forest
group4.forest
groupTLD.gov.it
group6.gov
As you can see from the examples, a couple of particles are found twice and that is not the behavior i sought for, anyway. Any attempt to edit the formula results in unexpeted output.
Any idea about a way to find the expected results?
This a simple, well-defined task. There is no fuzzyness, no complexity, no guessing, just a series of easy tests to figure out everything on your checklist. I have no idea how "machine learning" would be appropriate, or helpful. Even regex is completely unnecessary.
I've not implemented everything you want to verify, but it's not hard to fill in the missing bits.
import string
double_tld = ['gov', 'edu', 'co', 'add_others_you_need']
# we'll use this instead of regex to check subdomain validity
valid_sd_characters = string.ascii_letters + string.digits + '-'
valid_trans = str.maketrans('', '', valid_sd_characters)
def is_invalid_sd(sd):
return sd.translate(valid_trans) != ''
def check_hostname(hostname):
subdomains = hostname.split('.')
# each subdomain can contain only alphanumeric characters and
# the - character
invalid_parts = list(filter(is_invalid_sd, subdomains))
# TODO react if there are any invalid parts
# "the TLD can (optionally) contain a particle like
# .co, .gov, .edu and so on (.co.uk for example)"
if subdomains[-2] in double_tld:
subdomains[-2] += '.' + subdomains[-1]
subdomains = subdomains[:-1]
# "a maximum number of 126 subdomains plus the TLD"
# TODO check list length of subdomains
# "each subdomain must not begin or end with the - character"
# "the TLD must not be longer than 64 characters"
# "the TLD must not contain only digits"
# TODO write loop, check first and last characters, length, isnumeric
# TODO return something
I don't know if it is possible to get the output exactly as you asked. I think that with a single pattern it cannot catch results in different groups(group2, group3,..).
I found one way to get almost the result you expect using regex module.
match = regex.search(r'^(?:(?P<USAGE>autodiscover|correo|cpanel|ftp|mail|new|server|webdisk|webhost|webmail[\d]?|wiki|www[\d]?)\.)?(?:([a-z\d][a-z\d\-]{0,62}[a-z\d])\.){0,124}?(?P<TLD>(?:co|com|edu|net|org|gov)?\.(?!\d+)[a-z\d]{1,64})$', 'www.without.further.ado.lets.travel.the.forest.gov.it')
Output:
match.captures(0)
['www.without.further.ado.lets.travel.the.forest.gov.it']
match.captures[1] or match.captures('USAGE')
['www.']
match.captures(2)
['without', 'further', 'ado', 'lets', 'travel', 'the', 'forest']
match.captures(3) or match.captures('TLD')
['gov.it']
Here, to avoid taking . in groups I have added it in non-capturing group like this
(?:([a-z\d][a-z\d\-]{0,62}[a-z\d])\.)
Hope it helps.
Can anyone help me on this script?
What did the function do?
Thanks!
========================================================
&AAA=0
if (string.scan(string.lwr("¶meters"),"AAA",0)!=-1)
(
&AAA=1
)
========================================================
Well I guess your code looks like this:
&AAA=0
if (string.scan(string.lwr("¶meters"),"AAA",0)!=-1)
(
&AAA=1
)
Note: The round brackets for opening and closing a block in a PRACTICE script must be placed in separate lines.
About the meaning: Your script has two "variables" (aka. "macro"): ¶meters and &AAA.
In the first line you initialize &AAA with 0.
In the second line you use string.lwr() to get the content of the variable ¶meters converted to lower-case.
Then you search in this lower-case string for a string "AAA" (which is ironically upper case) beginning from the first letter (with string.scan()).
The result of string.scan() is -1 if the string "AAA" wasn't part of the lower-case version of ¶meters
So variable &AAA gets set to 1, if a lower-case version of ¶meters contain the string "AAA" (which is never the case since "AAA" is upper-case).
Maybe the writer of the script wanted to use string.upr() instead of string.lwr().
'registry/rabbit',
'registry/rabbit:3',
'rabbit',
'rabbit:3'
Trying to come up with a regex that will match rabbit in the four cases above. Seems easy enough, but my regex-fu is failing me.
The format is a little under-specified, but this seems to work:
^(?:(?=[^:\/]{1,253})(?!-)[a-zA-Z0-9-]{1,63}(?<!-)(?:\.(?!-)[a-zA-Z0-9-]{1,63}(?<!-))*(?::[0-9]{1,5})?/)?((?![._-])(?:[a-z0-9._-]*)(?<![._-])(?:/(?![._-])[a-z0-9._-]*(?<![._-]))*)(?::(?![.-])[a-zA-Z0-9_.-]{1,128})?$
From the docs:
An image name is made up of slash-separated name components, optionally prefixed by a registry hostname. The hostname must comply with standard DNS rules, but may not contain underscores. If a hostname is present, it may optionally be followed by a port number in the format :8080. If not present, the command uses Docker’s public registry located at registry-1.docker.io by default. Name components may contain lowercase characters, digits and separators. A separator is defined as a period, one or two underscores, or one or more dashes. A name component may not start or end with a separator.
A tag name may contain lowercase and uppercase characters, digits, underscores, periods and dashes. A tag name may not start with a period or a dash and may contain a maximum of 128 characters.
Tests are here.
You can try:
(?:[a-z]+/)?([a-z]+)(?::[0-9]+)?
But you need to read the spec to replace a-z and 0-9 to all possible characters.
Alternatively, this regex will capture the container name without regard for the specification other than / and ::
(?:.+/)?([^:]+)(?::.+)?
Sample data and test
def s = [
'registry.example.com/org/image-name',
'registry/org/image-name',
'registry/image-name',
'image-name',
'registry.example.com/org/image-name:version',
'registry/org/image-name:version',
'registry/image-name:version',
'image-name:version',
]
s.forEach {
def image = (s =~ "(?:.+/)?([^:]+)(?::.+)?")[0][1]
println image
assert image == 'image-name'
}
Will output:
image-name
image-name
image-name
image-name
image-name
image-name
image-name
image-name
There is another solution to this problem which contains all varieties and does not use lookaheads.
// image/tag:v1.0.0
// 123.123.123.123:123/image/tag:v1.0.0
// your-domain.com/image/tag
// your-domain.com/image/tag:v1.1.1-patch1
// image/tag
// image
// image:v1.1.1-patch
// ubuntu#sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2
// etc...
const dockerImageVerify = "^(([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])(:[0-9]+\\/)?(?:[0-9a-z-]+[/#])(?:([0-9a-z-]+))[/#]?(?:([0-9a-z-]+))?(?::[a-z0-9\\.-]+)?$"
This covers all cases.
To be precise, the question and almost all the answers have nothing to do with the docker image tag, but rather with the entire docker image name.
The regular expression for the image tag is much simpler:
/[a-zA-Z\d_][a-zA-Z\d-_.]{0,127}/
From the docs:
A tag name may contain lowercase and uppercase characters, digits, underscores,
periods and dashes. A tag name may not start with a period or a dash and may contain a
maximum of 128 characters.
The best source for the official regular expression would be the Go implementation for OCI references used by Docker itself.
To get the full pattern, we can build and execute the following:
package main
import (
"fmt"
"github.com/distribution/distribution/reference"
)
func main() {
fmt.Printf("%q\n", reference.ReferenceRegexp)
}
go mod init foo.example
go mod tidy
go run ./main.go
This gives us:
^((?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(?:(?:\\.(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]))+)?(?::[0-9]+)?/)?[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?(?:(?:/[a-z0-9]+(?:(?:(?:[._]|__|[-]*)[a-z0-9]+)+)?)+)?)(?::([\\w][\\w.-]{0,127}))?(?:#([A-Za-z][A-Za-z0-9]*(?:[-_+.][A-Za-z][A-Za-z0-9]*)*[:][[:xdigit:]]{32,}))?$
The capture groups are image name, image tag, and digest respectively.
I think this covers all:
const ipRegexStr = '((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))';
const hostnameRegexStr = '((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))';
const tagNameRegexStr = '([a-z0-9](\-*[a-z0-9])*)';
const tagVersionRegexStr = '([a-z0-9\_]([\-\.\_a-z0-9])*)';
const dockerRepoTagRegexStr = `^(${ipRegexStr}|${hostnameRegexStr}/)${tagNameRegexStr}(:${tagVersionRegexStr})?$`;
const dockerTagRegex = new RegExp(dockerRepoTagRegexStr);
console.log(dockerTagRegex.test('11.com/0-2:122--')); //true
console.log(dockerTagRegex.test('192.168.1.2/0---2:232-323-d-')); //true
console.log(dockerTagRegex.test('-0-2')); //false
console.log(dockerTagRegex.test('0-2-')); //false
console.log(dockerTagRegex.test('0-2:-23423')); //false
This is yet another iteration inspired by above answers. Ideally there should be a long-format in the docker-compose file so we don't have to break these up. I'm also not sure if I'm naming things the right way (registry/image/tag:label). I can't vouch for how much it follows spec, whether it is too strict or not strict enough, etc. YMMV.
this is Python (not JS) so may not apply to most in the devops tooling space
allows strict uppercase variable names for the image tag labels (${VAR_NAME})
enforces some sane character limits but I did not research what the spec allows
this code block is in VERBOSE mode and needs to be wrapped in re.compile("<block>", re.X) to allow for comments/whitespace to be removed
# FIRST we have the registry/image/tag:label format
(?:^
# registry
(?:(?P<registry>
(?:
# IPv4
(?P<reg_ip>(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))
|
# domain
(?P<reg_domain>(?:(?:[a-zA-Z][a-zA-Z0-9\-]{,48}[a-zA-Z0-9])\.){,4}(?:[A-Za-z]|[A-Za-z][A-Za-z0-9\-]{,48}[A-Za-z0-9]))
|
# hostname
(?P<reg_host>([A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9]))
)
# port
(?P<reg_port>:[0-9]+)?
)
# registry is optional, and not greedy
/)??
(?P<image>[0-9a-z_-]{1,40})
(?:/
(?P<tag>[0-9a-z_-]{1,40})
)?
# label can be a literal or a variable
(?::
(?P<label>[a-z0-9][a-z0-9._-]{1,38}[a-z0-9]|\${[A-Z][A-Z0-9_]{,38}[A-Z0-9]})
)?
# next we have the digest format
$)|(?:^
(?P<user>[a-zA-Z]\w{,25})
#sha256:
(?P<hashcode>[0-9a-f]{64})
$)
Here's a code-hint to render a new image string after changing parts of the parsed image string:
def __str__(self):
if self.image:
image_tag = '/'.join(filter(None, (self.image, self.tag)))
imag_tag_label = ':'.join(filter(None, (image_tag, self.label)))
return '/'.join(filter(None, (self.registry, imag_tag_label)))
return f'{self.user}#sha256:{self.hashcode}'