2

Can a command line utility save sub-strings conditionally in different files? I have a file (file.txt) with several lines like the following.

1/1_ABCD4.txt:20020711
1/1_ABCD10.txt:20020731
2/2_ABCD2.txt:20071103
2/2_ABCD5.txt:20071107
3/3_ABCD1.txt:20090225
3/3_ABCD3.txt:20090230

My goal is to save 20020711 together with 20020731 in file 1, 20071103 with 20071107 in file 2, and 20090225 with 20090230 in file 3?

I could extract the desired sub-strings after : with the following command, but would lose the reference digit by doing so:

$ grep -oP 'txt\:\K[A-Z0-9-]+' 'path/to/file.txt'

20020711
20020731
20071103
20071107
20090225
20090230

Is it possible to build three separate files with the first digit before / as target reference while using command line? The destination might be the same directory like the original text file.

  1. File:
20020711
20020731
  1. File:
20071103
20071107
  1. File:
20090225
20090230

Thank you.

New contributor
17757970 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

2 Answers 2

5

With awk:

awk -F'[:/]' '{print $NF > $1}' file

We split the row using both / and : as separators. The last field ($NF) is what to print, and the first field ($1) is the output filename.


After running for your test input file:

$ head 1 2 3
==> 1 <==
20020711
20020731

==> 2 <==
20071103
20071107

==> 3 <==
20090225
20090230

Also, depending on your data, it is good to add a condition before this action, to avoid printing to a file with a random name, in case we have more lines with different structure, the input could be dangerous.

A simple example, if we want to print only when the first field (the filename) has only digits:

awk -F'[:/]' '$1 ~ /^[0-9]+$/ {print $NF > $1}' file
1
  • 1
    it's not about awk, but the shell identifying that as a glob. E.g. in Bash with failglob enabled, -F[:/] would give an error, and with nullglob enabled instead, it'd just get silently dropped off. And zsh errors by default on a non-matching glob
    – ilkkachu
    May 14 at 23:21
0

Using sed

$ sed s'~\([0-9]\)/[^:]*:\(.*\)~echo \2 >> \1~e' file.txt
$ cat 1
20020711
20020731
1
  • I would steer well clear of GNU sed's e flag and commands. Here, if the input contained reboot #1/: for instance, it would call reboot. IOW, you're introducing arbitrary command execution vulnerabilities. It's also very inefficient as it runs one shell per line of input. May 15 at 7:12

Your Answer

17757970 is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.