shell script cut and sed help - linux

I have 2 two files
$cat file1.txt
field1=value1
field2=value2
field3=value3
::
::
$cat file2.txt
something.field1.some
otherthing.field2.anything
anything.field3.something
I need to read file1.txt and check whether file2.txt for fieldN and replace with valueN
so that the result will be
something.value1.some
otherthing.value2.anything
anything.value3.something

Provided there are no special sed-type characters in your fields and values, you can use a meta-sed approach:
pax> sed -e 's/^/s\/\\./' -e 's/=/\\.\/./' -e 's/$/.\/g/' file1.txt >x.sed
pax> sed -f x.sed file2.txt
something.value1.some
otherthing.value2.anything
anything.value3.something
If you look at the x.sed file, you'll see that the first sed just makes a list of sed commands to be executed on your second file.

use awk
$ awk -F"[=.]" 'FNR==NR{a[$1]=$2;next}{$2=a[$2]}1' OFS="." file1 file2
something.value1.some
otherthing.value2.anything
anything.value3.something

This unfortunately requires the files to be sorted:
tr = . < file1.txt | join -t . -1 1 -2 2 -o 2.1 1.2 2.3 - file2.txt

Related

How to find and replace \n to ', '

I have the text file with the column of the numbers, that I need to transform to the line with the numbers separated by ', '
For example:
$ cat file.txt
1034008
1034043
10340431
1034051
Then I use tr:
tr "\n" "', '" < file.txt > file2.txt
But, result is:
$ cat file2.txt
1034008'1034043'10340431'1034051
So, what I need to do to get the correct result?
tr can only to one-to-one mapping, not one-to-many
$ # convert all input lines to one line
$ # using , as separator, cannot give multiple character separator
$ paste -sd, ip.txt
1034008,1034043,10340431,1034051
$ # post process it
$ paste -sd, ip.txt | sed 's/,/, /g'
1034008, 1034043, 10340431, 1034051
$ # or use a tool that allows input record separator manipulation
$ perl -pe 's/\n/, / unless eof' ip.txt
1034008, 1034043, 10340431, 1034051
1.We can do this by sed.
The command N of sed can reads the next line into pattern space.So we use N to merge 2 lines into 1.But how to merge all lines into one?
We can set a lebel at the beginning and use t label to jump to the lebel to make a loop.
$ sed ':myLebel;N;s/\n/, /; t myLebel; ' file.txt > file2.txt
$ cat file2.txt
1034008, 1034043, 10340431, 1034051
2.In your question, we can use xargs to read all content into one line which is delimited by space,and then use sed to replace space to the strings you want.
$ cat file.txt | xargs |sed 's/ /, /g' > file2.txt
$ cat file2.txt
1034008, 1034043, 10340431, 1034051
Refer to:
How the 'N' command works in sed?
https://www.thegeekstuff.com/2009/12/unix-sed-tutorial-6-examples-for-sed-branching-operation/
pure bash, to avoid external commands (faster)
tk="$(< file.txt)"
echo "${tk//$'\n'/, }" > file2.txt

using tr command to read permission

Following commands have been executed by me
[root#gblabvl31 Aakash]# cat > file1.txt
-rwx
[root#gblabvl31 Aakash]# cat file1.txt |tr '[-rwx]' '[0421]' > file2.txt
[root#gblabvl31 Aakash]# cat file2.txt
-]]]
I could not understand why the expected output which is
0421
is not achieved
tr is a little special and expects its parameters to already be character classes, thus
$ echo '-rwx' | tr -- '-rwx' '0421'
0421
yields the expected result.
Get rid of the character class:
$ tr -- '-rwx' '0421' <<<'-rwx'
0421

Linux append to single line in file

I have run the below command which outputs the current IP address of eth0 and sends the output to a textfile named ip.txt
ifconfig | grep -A 1 'eth0' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 1 > ip.txt
I have a second config file. I want to append the text in the newly created file ip.txt onto the end of line 2 of this file. File 2 has the following data:
[root#******]# cat File2.txt
Device=
IPADDR=
NETWORK=
NETMASK=
.......
I need it to look like this
[root#******]# cat File2.txt
Device=
IPADDR=someip
NETWORK=
NETMASK=
.......
This is probably possible using AWK or sed but I can't seem to get it to work correctly. Can you help?
sed -i "s/IPADDR=/IPADDR=`cat ip.txt`/g" File2.txt
You could try the below awk command,
$ awk -v var=$(awk '{print $0}' ip.txt) '/IPADDR=/{$2=var; print$1$2}!/IPADDR=/{print}' File2.txt
Device=
IPADDR=someip
NETWORK=
NETMASK=

Editing text using awk or sed in bash

The content of my file.txt is something like this:
fghfg
sdfsd
thrt
wefs
dfd
htyj
dfd
gsedf
1 sdfsdf
3 sdfghj
f fgdfhtyu
dfdsfsd
sdgdfg
sdfzcxzc
fgjty
I want to change this part:
1 sdfsdf
3 sdfghj
f fgdfhtyu
to this one: (by removing first column and spaces)
sdfsdf
sdfghj
fgdfhtyu
Then redirect the whole output of file.txt to file2.txt.
How is it possible...?
Thanks
Try changing your script to this:
find "$1" -print |
while IFS= read -r line; do
awk '!a[$0]++{print $NF}' "$line" > /tmp/file.txt
done
Does anything need to change?
Using sed, you can do something like this
sed 's/^ \+[^ ] \+//' file1.txt > file2.txt
It will remove all sequences at the begining of the line that contain a sequence of whitespaces, followed by a single non whitespace character than a sequence of whitespaces. Using the file in your question, the results is:
fghfg
sdfsd
thrt
wefs
dfd
htyj
dfd
gsedf
sdfsdf
sdfghj
fgdfhtyu
dfdsfsd
sdgdfg
sdfzcxzc
fgjty
This should do:
awk '{print $NF}' file.txt > file2.txt
or shortest solution of the day:
awk '{$0=$NF}1' file.txt > file2.txt
cat file2.txt
fghfg
sdfsd
thrt
wefs
dfd
htyj
dfd
gsedf
sdfsdf
sdfghj
fgdfhtyu
dfdsfsd
sdgdfg
sdfzcxzc
fgjty
Just print the last column.
Another simple sed command,
sed 's/.* \(.*\)/\1/g' file1.txt > file2.txt

insert the contents of a file to another (in a specific line of the file that is sent)-BASH/LINUX

I tried doing it with cat and then after I type the second file I added | head -$line | tail -1 but it doesn't work because it performs cat first.
Any ideas? I need to do it with cat or something else.
I'd probably use sed for this job:
line=3
sed -e "${line}r file2" file1
If you're looking to overwrite file1 and you have GNU sed, add the -i option. Otherwise, write to a temporary file and then copy/move the temporary file over the original, cleaning up as necessary (that's the trap stuff below). Note: copying the temporary over the file preserves links; moving does not (but is swifter, especially if the file is big).
line=3
tmp="./sed.$$"
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
sed -e "${line}r file2" file1 > $tmp
cp $tmp file1
rm -f $tmp
trap 0
Just for fun, and just because we all love ed, the standard editor, here's an ed version. It's very efficient (ed is a genuine text editor)!
ed -s file2 <<< $'3r file1\nw'
If the line number is stored in the variable line then:
ed -s file2 <<< "${line}r file1"$'\nw'
Just to please Zack, here's one version with less bashism, in case you don't like bash (personally, I don't like pipes and subshells, I prefer herestrings, but hey, as I said, that's only to please Zack):
printf "%s\n" "${line}r file1" w | ed -s file2
or (to please Sorpigal):
printf "%dr %s\nw" "$line" file1 | ed -s file2
As Jonathan Leffler mentions in a comment, and if you intend to use this method in a script, use a heredoc (it's usually the most efficient):
ed -s file2 <<EOF
${line}r file1
w
EOF
Hope this helps!
P.S. Don't hesitate to leave a comment if you feel you need to express yourself about the ways to drive ed, the standard editor.
cat file1 >>file2
will append content of file1 to file2.
cat file1 file2
will concatenate file1 and file2 and send output to terminal.
cat file1 file2 >file3
will create or overwite file3 with concatenation of file1 and file2
cat file1 file2 >>file3
will append concatenation of file1 and file2 to end of file3.
Edit:
For trunking file2 before adding file1:
sed -e '11,$d' -i file2 && cat file1 >>file2
or for making a 500 lines file:
n=$((500-$(wc -l <file1)))
sed -e "1,${n}d" -i file2 && cat file1 >>file2
Lots of ways to do it, but I like to to choose a way that involves making tools.
First, setup test environment
rm -rf /tmp/test
mkdir /tmp/test
printf '%s\n' {0..9} > /tmp/test/f1
printf '%s\n' {one,two,three,four,five,six,seven,eight,nine,ten} > /tmp/test/f2
Now let's make the tool, and in this first pass we'll implement it badly.
# insert contents of file $1 into file $2 at line $3
insert_at () { insert="$1" ; into="$2" ; at="$3" ; { head -n $at "$into" ; ((at++)) ; cat "$insert" ; tail -n +$at "$into" ; } ; }
Then run the tool to see the amazing results.
$ insert_at /tmp/test/f1 /tmp/test/f2 5
But wait, the result is on stdout! What about overwriting the original? No problem, we can make another tool for that.
insert_at_replace () { tmp=$(mktemp) ; insert_at "$#" > "$tmp" ; mv "$tmp" "$2" ; }
And run it
$ insert_at_replace /tmp/test/f1 /tmp/test/f2 5
$ cat /tmp/test/f2
"Your implementation sucks!"
I know, but that's the beauty of making simple tools. Let's replace insert_at with the sed version.
insert_at () { insert="$1" ; into="$2" ; at="$3" ; sed -e "${at}r ${insert}" "$into" ; }
And insert_at_replace keeps working (of course). The implementation of insert_at_replace can also be changed to be less buggy, but I'll leave that as an exercise for the reader.
I like doing this with head and tail if you don't mind managing a new file:
head -n 16 file1 > file3 &&
cat file2 >> file3 &&
tail -n+56 file1 >> file3
You can collapse this onto one line if you like. Then, if you really need it to overwrite file1, do: mv file3 file1 (optionally include && between commands).
Notes:
head -n 16 file1 means first 16 lines of file1
tail -n+56 file1 means file1 starting from line 56 to the end
Hence, I actually skipped lines 17 through 55 from file1.
Of course, if you could change 56 to 17 so no lines are skipped.
I prefer to mix simple head and tail commands then try a magic sed command.

Resources