Reformating data with awk command depending on a if condition - bash

i have a script that reformated the content of a source file in a target file.
It does it for every files in a directory.
Here is a source file exemple :
TABLE;APGFPOLI;
Contrat;CHAR(16);Numéro du contrat
Libelle;CHAR(30);Libellé du contrat
DtCreation;CHAR(8);Date de création
DtMaj;CHAR(8);Date de dernière MAJ
DtEffet;CHAR(8);Date d'effet adhésion
MotifAdh;CHAR(2);Motif d'adhésion
DtRadiation;CHAR(8);Date de radiation
DtEnrRad;CHAR(8);Date enregistrement radiat
MotifRad;CHAR(2);Motif de radiation
MtPrime;Numérique 8.2;Montant prime d'origine
DtEffetSusp;CHAR(8);Date d'effet de suspension
DtFinSusp;CHAR(8);Date de fin de suspension
MotifSusp;CHAR(2);Motif de suspension
DestBord;CHAR(1);Destinataire du bordereau
CdDest;CHAR(5);Code du destinataire
NivRupBord;CHAR(1);Niveau rupture bordereau
BordCETIP;CHAR(1);Bordereau CTIP
EnvBordNom;CHAR(1);Envoi bordereau nominatif
Indice;CHAR(2);Indice appliqué
Echeance;CHAR(2);Echéance de l'indice (MM)
Effectif;CHAR(5);Effectif
CdRegr;CHAR(3);Code regroupement 1
CdGroupe;CHAR(3);Code regroupement 2
Periodicite;CHAR(1);Périodicité
Terme;CHAR(1);Terme
Produit;CHAR(6);Code produit affecté
Inspecteur;CHAR(5);Inspecteur
CleInsp;CHAR(1);Clé inspecteur
Filler;CHAR(6);Filler
And here is the target file generated by the shell:
01 APGFPOLI.
* Numéro du contrat.
05 Contrat PIC X(16).
* Libellé du contrat.
05 Libelle PIC X(30).
* Date de création.
05 DtCreation PIC X(8).
* Date de dernière MAJ.
05 DtMaj PIC X(8).
* Date d'effet adhésion.
05 DtEffet PIC X(8).
* Motif d'adhésion.
05 MotifAdh PIC X(2).
* Date de radiation.
05 DtRadiation PIC X(8).
* Date enregistrement radiat.
05 DtEnrRad PIC X(8).
* Motif de radiation.
05 MotifRad PIC X(2).
* Montant prime d'origine.
05 MtPrime Numérique 8.2.
* Date d'effet de suspension.
05 DtEffetSusp PIC X(8).
* Date de fin de suspension.
05 DtFinSusp PIC X(8).
* Motif de suspension.
05 MotifSusp PIC X(2).
* Destinataire du bordereau.
05 DestBord PIC X(1).
* Code du destinataire.
05 CdDest PIC X(5).
* Niveau rupture bordereau.
05 NivRupBord PIC X(1).
* Bordereau CTIP.
05 BordCETIP PIC X(1).
* Envoi bordereau nominatif.
05 EnvBordNom PIC X(1).
* Indice appliqué.
05 Indice PIC X(2).
* Echéance de l'indice (MM).
05 Echeance PIC X(2).
* Effectif.
05 Effectif PIC X(5).
* Code regroupement 1.
05 CdRegr PIC X(3).
* Code regroupement 2.
05 CdGroupe PIC X(3).
* Périodicité.
05 Periodicite PIC X(1).
* Terme.
05 Terme PIC X(1).
* Code produit affecté.
05 Produit PIC X(6).
* Inspecteur.
05 Inspecteur PIC X(5).
* Clé inspecteur.
05 CleInsp PIC X(1).
* Filler.
05 Filler PIC X(6).
What i am trying to do is change that line :
MtPrime;Numérique 8.2;Montant prime d'origine
Like this :
05 MtPrime PIC 9(8).v9(2).
As you can see it changed "Numérique X.Y" by PIC 9(X).v9(Y).
The condition is that if i have only one number "X" after "Numerique" i need to reformat it like this :
"PIC 9(X)"
BUT if i have a number "X" DOT another number "Y" i need to print it like this :
"PIC 9(X).v9(Y)"
Using awk command and being a full beginner i have no clue how can i achieve this.
Here is my shell :
#!/bin/bash
SOURCE_DIRECTORY="/home/yha/AG2R/SOURCE/*"
TARGET_DIRECTORY="/home/yha/AG2R/COPY/"
for f in $SOURCE_DIRECTORY
do
b=$(basename "$f")
echo "Processing $f file..";
awk -F ';' '$1=="TABLE" && $3=="" {printf "01 %s.\n\n", $2; next} {sub(/CHAR/,"PIC X", $2);printf " * %s.\n\n 05 %s %s.\n\n", $3, $1, $2;}' "$f" > "$TARGET_DIRECTORY/$b.cpy"
done

For the awk part, you might use a regex to check for the word followed by a digits and an optional part with a dot and digits.
^Numérique [0-9]+(\.[0-9]+)?$
If there is a match, you can split on a space or dot. Then you can assemble the string to print by checking if there is a 3rd entry in the array with splitted values and start the string with the value of the 2nd value.
The data
$cat file
TABLE;APGFPOLI;
DtEnrRad;CHAR(8);Date enregistrement radiat
MotifRad;CHAR(2);Motif de radiation
MtPrime;Numérique 8.2;Montant prime d'origine
MtPrime;Numérique 5;Montant prime d'origine
DtEffetSusp;CHAR(8);Date d'effet de suspension
awk script
awk -F ';' '
$1=="TABLE" && $3=="" {
printf "01 %s.\n\n", $2;
next
}
{
result = $2
if ($2 ~ /^Numérique [0-9]+(\.[0-9]+)?$/) {
nr=split($2,a,"[ .]")
result = "PIC 9(" a[2] ")"
if (nr == 3) {
result = result ".v9(" a[3] ")"
}
}
sub(/CHAR/,"PIC X", result);
printf " * %s.\n\n 05 %s %s.\n\n", $3, $1, result;
}' file
Output
01 APGFPOLI.
* Date enregistrement radiat.
05 DtEnrRad PIC X(8).
* Motif de radiation.
05 MotifRad PIC X(2).
* Montant prime d'origine.
05 MtPrime PIC 9(8).v9(2).
* Montant prime d'origine.
05 MtPrime PIC 9(5).
* Date d'effet de suspension.
05 DtEffetSusp PIC X(8).

Related

Execute command on each line in a file

I have a list of ids in one file that I want to use to grep their information from a second file. I can only get my output to show only the information for the last id and I think I just can't figure out how to tweak my code a bit so that it outputs the info for each line, not the last one only.
my command:
for i in $(cat my_ids.txt);
do
for name in $i;
do
class=$(grep -A 25 $name id_info.txt | grep -E "tf_class");
family=$(grep -A 25 $name id_info.txt | grep -E "tf_family");
echo -e "$name\n\class\n\family";
done
done
I only get the last id's information lines that I need. I need it to show up for each ID and I don't know how else to tweak this. I also tried removing the second for loop but it was giving the exact same output.
Sample input from my_ids.txt:
MA0052.4
MA0602.1
MA0497.1
MA0786.1
MA0515.1
Sample input from id_info.txt
AC MA0052.4
XX
ID MEF2A
XX
DE MA0052.4 MEF2A ; From JASPAR
PO A C G T
01 5075.0 2119.0 3651.0 5317.0
02 4033.0 1960.0 4493.0 5676.0
03 1984.0 10919.0 1007.0 2252.0
04 627.0 2974.0 236.0 12325.0
05 12437.0 1013.0 1066.0 1646.0
06 13132.0 253.0 610.0 2167.0
07 14680.0 141.0 506.0 835.0
08 14453.0 231.0 241.0 1237.0
09 14956.0 173.0 202.0 831.0
10 441.0 349.0 215.0 15157.0
11 15582.0 50.0 422.0 108.0
12 2566.0 1060.0 11104.0 1432.0
13 7709.0 4039.0 1605.0 2809.0
14 6171.0 3523.0 1810.0 4658.0
15 5254.0 3812.0 2479.0 4617.0
XX
CC tax_group:vertebrates
CC tf_family:Regulators of differentiation
CC tf_class:MADS box factors
CC pubmed_ids:25217591
CC uniprot_ids:Q02078
CC data_type:ChIP-seq
AC MA0602.1
XX
ID Arid5a
XX
DE MA0602.1 Arid5a ; From JASPAR
PO A C G T
01 18.0 43.0 23.0 17.0
02 16.0 32.0 3.0 48.0
03 85.0 3.0 7.0 5.0
04 96.0 0.0 1.0 2.0
05 6.0 0.0 1.0 93.0
06 93.0 1.0 1.0 6.0
07 2.0 1.0 1.0 96.0
08 4.0 9.0 4.0 83.0
09 23.0 3.0 52.0 22.0
10 34.0 35.0 18.0 12.0
11 29.0 13.0 27.0 31.0
12 57.0 8.0 19.0 16.0
13 29.0 18.0 26.0 27.0
14 34.0 23.0 15.0 27.0
XX
CC tax_group:vertebrates
CC tf_family:ARID-related
CC tf_class:ARID
CC pubmed_ids:25215497
CC uniprot_ids:Q3U108
CC data_type:PBM
XX
AC MA0497.1
XX
ID MEF2C
XX
DE MA0497.1 MEF2C ; From JASPAR
PO A C G T
01 705.0 321.0 676.0 507.0
02 733.0 151.0 573.0 752.0
03 431.0 196.0 822.0 760.0
04 382.0 1412.0 78.0 337.0
05 0.0 985.0 0.0 1224.0
06 1616.0 256.0 74.0 263.0
07 1706.0 32.0 241.0 230.0
08 2107.0 0.0 87.0 15.0
09 2131.0 0.0 2.0 76.0
10 2135.0 0.0 4.0 70.0
11 56.0 62.0 0.0 2091.0
12 2177.0 0.0 32.0 0.0
13 389.0 120.0 1671.0 29.0
14 975.0 836.0 148.0 250.0
15 1009.0 450.0 126.0 624.0
XX
CC tax_group:vertebrates
CC tf_family:Regulators of differentiation
CC tf_class:MADS box factors
CC pubmed_ids:7559475
CC uniprot_ids:Q06413
CC data_type:ChIP-seq
XX
AC MA0786.1
XX
ID POU3F1
XX
DE MA0786.1 POU3F1 ; From JASPAR
PO A C G T
01 1034.0 126.0 322.0 1437.0
02 505.0 186.0 128.0 2471.0
03 2471.0 7.0 26.0 21.0
04 44.0 53.0 21.0 2471.0
05 37.0 13.0 2471.0 232.0
06 170.0 2471.0 413.0 1119.0
07 1423.0 1.0 21.0 1048.0
08 2471.0 103.0 130.0 284.0
09 2471.0 20.0 25.0 63.0
10 259.0 95.0 128.0 2471.0
11 382.0 302.0 620.0 1167.0
12 1510.0 478.0 452.0 961.0
XX
CC tax_group:vertebrates
CC tf_family:POU domain factors
CC tf_class:Homeo domain factors
CC pubmed_ids:1361172
CC uniprot_ids:Q03052
CC data_type:HT-SELEX
XX
AC MA0515.1
XX
ID Sox6
XX
DE MA0515.1 Sox6 ; From JASPAR
PO A C G T
01 4.0 139.0 50.0 56.0
02 0.0 221.0 0.0 28.0
03 161.0 0.0 0.0 88.0
04 0.0 0.0 0.0 249.0
05 0.0 0.0 0.0 249.0
06 0.0 0.0 249.0 0.0
07 0.0 0.0 0.0 249.0
08 0.0 115.0 5.0 129.0
09 4.0 112.0 0.0 133.0
10 14.0 76.0 31.0 128.0
XX
CC tax_group:vertebrates
CC tf_family:SOX-related factors
CC tf_class:High-mobility group (HMG) domain factors
CC pubmed_ids:21985497
CC uniprot_ids:P40645
CC data_type:ChIP-seq
XX
Example of the output I get when I run this as a bash script:
MA0052.4
MA0602.1
MA0497.1
MA0786.1
MA0515.1 CC tf_class:High-mobility group (HMG) domain factors CC tf_family:SOX-related factors
Desired output:
MA0602.1 CC ARID CC ARID-related
MA0497.1 CC MADS box factors CC Regulators of differentiation
MA0786.1 CC Homeo domain factors CC POU domain factors
MA0515.1 CC tf_class:High-mobility group (HMG) domain factors CC tf_family:SOX-related factors
Another code snippet I tried but the output just gives me id names and nothing more; probably because I am messing up the syntax somehow (ran this in terminal):
while IFS= read -r line; do class=$(grep -A 25 $line id_infoc.txt | grep -E "tf_class"); family=$(grep -A 25 $line id_info.txt | grep -E "tf_family"); echo -e "$line\n\class\n\family"; done < my_ids.txt
Try this script:
#! /usr/bin/env bash
while read -r id; do
name="$id"
class=$( grep -A 25 "$name" id_info.txt | grep -E "tf_class")
family=$(grep -A 25 "$name" id_info.txt | grep -E "tf_family")
echo -e "${name}\n${class}\n${family}"
done <"my_ids.txt"
Ignoring style, the bug in your code is that you use \family and \class instead of $family and $class.
Invoking grep multiple times as you do will be a bit inefficient if the file is large and there are many ids to check.
A straightforward solution in awk that only needs to read each file once might be:
awk '
function do_print () {
if (name in ids)
printf("%s\n%s\n%s\n",name,class,family)
name=family=class=""
}
# read ids into an array
NR==FNR { ids[$0]; next }
# start of a section
/^AC / { do_print(); name=$2; next }
# other candidate values found
/^CC tf_family:/ { family=$0; next }
/^CC tf_class:/ { class=$0; next }
# maybe print final section
END { do_print() }
' my_ids.txt id_info.txt
To filter out the tf_family:,etc, the regexes can be replaced by sub:
sub(/^CC tf_family:/,"CC ") { family=$0; next }
sub(/^CC tf_class:/,"CC ") { class=$0; next }

Apple pay EMV transaction

I am trying to perform Apple pay transaction. The card edded to apple pay wallet is MasterCard. If I perform a contactless transaction using a physical card, my code works. But when I try to do the same with ApplePay, I get SW 6700 (wrong length) status after the GENERATE AC command.
Here you can see how I construct data for GAC request:
9f02 06 000000000100 Amount, Authorised (Numeric)
9f03 06 000000000000 Amount, Other (Numeric)
9f1a 02 0804 Terminal Country Code
95 05 0000000000 Terminal Verification Results
5f2a 02 0980 Transaction Currency Code
9a 03 210511 Transaction Date
9c 01 00 Transaction Type
9f37 04 3357A30A Unpredictable Number
9f35 01 21 Terminal Type
9f45 02 0000 Data Authentication Code
9f4c 08 0000000000000000 ICC Dynamic Number
9f34 03 1F0302 Cardholder Verification Method (CVM) Results
9f21 03 131340 Transaction Time HHMMSS
9f7c 14(20 dec) 0000000000000000000000000000000000000000 Customer Exclusive Data (CED)
So, my final data is:
80 AE 8000 42 000000000030 000000000000 0804 0000008001 0980 210511 00 3357A30A 21 0000 0000000000000000 1F0302 133040 0000000000000000000000000000000000000000 00
Le byte is 42 (66 dec) and it is correct if physical card is used.
What is wrong with Apple Pay?
The problem is that CDOL1 differs when using ApplePay with the same card.
Thus tag 0x8C (CDOL1) using ApplePay is:
9f02069f03069f1a0295055f2a029a039c019f37049f35019f45029f4c089f34039f1d089f15029f4e14
And using physical contactless card (MasterCard):
9f02069f03069f1a0295055f2a029a039c019f37049f35019f45029f4c089f34039f21039f7c14
So, they are not equal, and deconstruction gives us such a data items:
9f02 06 000000000100
9f03 06 000000000000
9f1a 02 0804
95 05 0000000000
5f2a 02 0980
9a 03 210511
9c 01 00
9f37 04 3357A30A
9f35 01 21
9f45 02 0000
9f4c 08 0000000000000000
9f34 03 1F0302
9f1d 08 6CF8000000000000
9f15 02 0000
9f4e 14 0000000000000000000000000000000000000000
So, the final data for GENERATE AC command should be:
80 AE 8000 49 000000000030 000000000000 0804 0000008001 0980 210511 00 3357A30A 21 0000 0000000000000000 1F0302 6CF8000000000000 0000 0000000000000000000000000000000000000000 00
Le = 73 dec / 0x49 hex.
This works fine.

Sed command to find string and replace another string (txt format)

I'm triying to find a string in a txt format and each time it's found then look for an specific string to change for another string.
Imagine the next hexa txt:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14
I need that each time I encounter a 2a sequence to look for 09 01 sequence and replace with 03 02.
Expected output:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
Im triying something this:
sed -i 's/09 01\(.*2a\)/03 02/g' packet.txt
I would do this with awk:
$ awk ' { for ( i = 1; i <= NF; ++i ) {
if ( $i == "2a" )
r = 1
if ( r && $i == "09" && $(i+1) == "01" ) {
r = 0
$i = "03"
$++i = "02"
}
}
}
1 ' hexa.txt > hexa.txt.modified
Grep the differences:
$ sdiff hexa.txt hexa.txt.modified
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1 02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01 09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14 | b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1 00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01 09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14 | b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
Assuming you mean: "only replace if it occurs after 2a", then you can do it by transforming the bytes, so that only one 2a occurs on each line, e.g.:
<hexa.txt tr '\n' ' ' | sed 's/2a/\n&/g'
Now all you need to do is only replace 09 01 when the line starts with 2a, e.g.:
sed -E 's/(^2a.*) 09 01/\1 03 02/'
Now go back to the original formatting, i.e. 16 bytes per line:
tr '\n' ' ' | xargs -n16
All together:
<hexa.txt tr '\n' ' ' | sed 's/2a/\n&/g' |
sed -E 's/(^2a.*) 09 01/\1 03 02/' |
tr '\n' ' ' | xargs -n16
Output:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
If this can help,
cat *.txt | sed '/2a/s/09 01/02 03/g'
Alternative awk solution using GNU awk:
awk 'BEGIN { RS="2a" } { ORS=RS } $0 ~ /09 01/ { $0=gensub("09 01","03 02","g",$0)}1' file
Set 2a as the record separator. Check each record for "09 01". If it exists, replace "09 01" with "03 02" with the gensub function and set this as $0. Use short hand 1 to print the record after setting the output record separator the same as the record separator.
This might work for you (GNU sed):
sed -zE 's/^/\x00/ # introduce a unique delimiter
:a;/\x00$/{s///;b} # remove delimiter at end-of-file
/\x002a/!{s/\x00(.)/\1\x00/;ba} # if not 2a pass over next char
s//2a\x00/ # next char is 2a prep for next string
:b;/\x00$/ba # is it end of file
/\x0009(\s)01/{s//03\102\x00/;ba} # replace string and prep for 2a again
s/\x00(.)/\1\x00/;bb' file # not desired string so pass over char
Since the desired string (in this case09 01) may occur on another line or within in the same line twice or more, line processing is not feasible. Processing must be at character level and in this solution the entire file is processed as one string (see -z option).
Two cases are identified:
The key (in this case 2a), processing within the place holder :a.
The string to be replaced (09 01 with 03 02), processing within the place holder :b.
Once the key is identified, processing passes to the next case. Once the desired string has been replaced, processing is passed back the first case. Either case can terminate processing when the end-of-file is encountered.
N.B. The solution relies on the file not containing the null character hex 00.

GNU linker - How to fill unused memory space

Some sections within my program are located at different places in memory and there are some unused memory locations. The following is a part of the object file of my program:
a0000128: 20cf8f93 addi t6,t6,524 # a0000330 <region_1>
a000012c: 000f8067 jr t6
Disassembly of section .fill:
00000000a0000130 <_end-0x800290>:
a0000130: deaa sw a0,124(sp)
a0000132: c0ad beqz s1,a0000194 <_start+0x194>
a0000134: dede sw s7,124(sp)
a0000136: c0ad beqz s1,a0000198 <_start+0x198>
...
Disassembly of section .s_region_1:
00000000a0000330 <region_1>:
a0000330: 00400f97 auipc t6,0x400
a0000334: 00cf8f93 addi t6,t6,12 # a040033c <region_2>
a0000338: 000f8067 jr t6
As shown, instruction at address 0xa000012c jumps to another instruction at address 0xa0000330. Since there are unused memory locations, I used FILL command in linker script. However, corresponding HEX file (generated with objcopy -O verilog) does not include the machine code of region_1. That is, HEX file only includes .text section and the data that is used to pad unused memory region:
13 0F 00 00 9B 0F 10 00 93 9F FF 01 1B 08 F0 FF
13 18 38 03 13 08 18 04 13 18 C8 00 13 08 98 12
73 10 18 30 97 0F 00 00 93 8F CF 20 67 80 0F 00
#A0000130
AA DE AD C0 DE DE AD C0 DE DE AD C0 DE DE AD C0
DE DE AD C0 DE DE AD C0 DE DE AD C0 DE DE AD C0
DE DE AD C0 DE DE AD C0 DE DE AD C0 DE DE AD C0
DE DE AD C0 DE DE AD C0 DE DE AD C0 DE DE AD C0
...
The following is the content of the linker script:
SECTIONS
{
. = 0xA0000000;
.text : { *(.text) }
.fill :
{
FILL(0xDEADC0DE);
BYTE(0xAA);
. = . + 0x1FF;
}
.s_region_1 : { *(s_region_1) }
.bss : { *(.bss) }
_end = .;
}
What is wrong with the linker script above?
This is the memory map I want to generate:
/*************************/
.text
/*************************/
/* EMPTY REGION */
/*************************/
.section_1
/*************************/
I noticed that I have to add "aw" flags within my assembly code when defining the section:
.section ".sregion1","aw"
region_1:
la x31, region_2
jr x31
After adding "aw" flags, the HEX file was generated by objcopy as expected:
#80000000
1B 00 10 00 13 10 F0 01 B7 F0 0F 00 9B 80 70 81
93 90 C0 00 93 80 90 A5 13 01 80 00 93 01 80 00
1B 02 10 00 13 12 F2 01 B7 B2 0F 00 9B 82 12 FB
...
#80400130
97 0F 00 00 93 8F CF 00 67 80 0F 00 97 0F 00 00
93 8F 0F 00 67 80 0F 00
The following is the final version of my linker file:
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
/*
MEMORY {
text (RX): o = 0x80000000, LENGTH = 128M
s_region_1 (RX): o = 0x80400000, LENGTH = 256K
}
*/
SECTIONS
{
. = 0x80000000;
.text :
{
*(.text);
}
. = . + 0x400000;
.sregion1 : { *(.sregion1) }
. = . + 0x400000;
.bss : { *(.bss) }
_end = .;
}

Count number of files and print the last file

I am missing some episodes of the TV series friends, and I would like to know how many files I am missing per season. I would like to print out the last episode of each season and the number of files for each season.
The files have the format:
Friends S01E01 The Pilot.mkv
Friends S10E11 The One Where the Stripper Cries.mkv
The following bash script/oneliner should give you what you need, with details because it might help if you have the last episode of a season but earlier episodes are missing:
#!/bin/bash
ls Friends* | cut -c10-14 | \
awk -F'E' '{arr[$1]=arr[$1]" "$2; num[$1]++;} END { for (i in arr) printf "Season %s (%2d files) : %s\n", i, num[i], arr[i] }' | \
sort
Using awk, arrays with index being the number of the season are incremented to count the number of episodes, and also print the list of episode numbers so you can easily see which ones are missing. I used cut with columns 10 to 14 because in this case, we can safely assume that the numbers are where we want them.
The output is as follows:
Season 01 ( 9 files) : 01 02 03 04 05 06 07 08 09
Season 02 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 03 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 04 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 05 ( 9 files) : 01 03 04 05 06 07 08 09 10
Season 06 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 07 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 08 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 09 (10 files) : 01 02 03 04 05 06 07 08 09 10
Season 10 ( 7 files) : 01 02 03 04 05 06 10
The following bash scipt will work:
#!/bin/bash
for i in {01..10}
do
ls Friends\ S$i* | tail -n 1
ls Friends\ S$i* | wc -l
printf "\n"
done
It will produce results as follows:
Friends S01E24 The One Where Rachel Finds Out.mkv
24
Friends S02E24 The One with Barry and Mindy's Wedding.mkv
24

Resources