How to Automatically Replace Numeric Citations with Citation Keys in LaTeX Using PowerShell
A practical guide for researchers and students to automate the conversion of numeric citations to proper citation keys in LaTeX documents using PowerShell scripting.
We’ve all been there. You’re wrapping up a paper in LaTeX, and you realize your document is full of \cite{1}, \cite{2}, \cite{3}… but your .bib file uses proper keys like smith2023keyword. Now you’re staring at dozens — maybe hundreds — of citations that need fixing, one by one.
I ran into this exact problem while working on a manuscript last year. After spending way too long doing it by hand (and making a few mistakes along the way), I wrote a short PowerShell script to handle it automatically. It saved me a ton of time, and I think it might help you too.
What’s the Problem, Exactly?
Here’s what it usually looks like. Your .tex file has something like this:
1
Recent advances have revolutionized the field \cite{1}\cite{2}.
Meanwhile, your .bib file has proper entries like:
1
2
3
4
5
6
@article{smith2023keyword,
title={Title of the First Paper},
author={Smith, John and Lee, Jane},
journal={Journal Name},
year={2023}
}
See the mismatch? Your document says \cite{1}, but it should say \cite{smith2023keyword}. When you only have a few references, it’s no big deal. But when you have 50 or 100? That’s where things get painful.
The Fix: A Simple PowerShell Script
The idea is straightforward — we tell the script which number maps to which citation key, and it does all the replacing for us. No more Ctrl+H marathons.
Before You Start
You’ll need:
- A Windows PC (PowerShell is already there)
- Your
.texfile with numeric citations - Your
.bibfile so you know the correct keys - About 5–10 minutes
Step 1: Set Up Your Citation Mapping
Take a look at your .bib file and note down which number corresponds to which citation key. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%1
@article{smith2023keyword,
title={Title of the First Paper},
author={Smith, John and Lee, Jane},
journal={Journal Name One},
year={2023}
}
%2
@inproceedings{doe2024analysis,
title={Title of the Second Paper},
author={Doe, Alice and Park, James},
booktitle={Proceedings of the Conference Name},
pages={100--115},
year={2024}
}
So 1 maps to smith2023keyword, 2 maps to doe2024analysis, and so on. Just keep adding entries for as many references as you have.
Step 2: The PowerShell Script
Here’s the full script. You can copy it as-is and just update the mapping part with your own citation keys:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# LaTeX Citation Replacement Script
# Replaces \cite{number} with \cite{citationkey}
# Create the citation mapping (add as many as you need)
$citationMap = @{
'1' = 'smith2023keyword'
'2' = 'doe2024analysis'
# '3' = 'your_next_key_here'
}
# Interactive file selection
Write-Host "Please select your LaTeX file..." -ForegroundColor Cyan
Add-Type -AssemblyName System.Windows.Forms
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Filter = "LaTeX files (*.tex)|*.tex|All files (*.*)|*.*"
$openFileDialog.Title = "Select your LaTeX file"
if ($openFileDialog.ShowDialog() -eq 'OK') {
$inputFile = $openFileDialog.FileName
$outputFile = $inputFile -replace '\.tex$', '_updated.tex'
Write-Host "Selected: $inputFile" -ForegroundColor Green
} else {
Write-Host "No file selected. Exiting." -ForegroundColor Red
exit
}
# Read the file
Write-Host "`nProcessing file..." -ForegroundColor Cyan
$content = Get-Content $inputFile -Raw
# Count citations
$beforeCount = ([regex]::Matches($content, '\\cite\{\d+\}')).Count
Write-Host "Found $beforeCount numeric citations" -ForegroundColor Yellow
# Replace citations using regex
$pattern = '\\cite\{(\d+)\}'
$result = [regex]::Replace($content, $pattern, {
param($match)
$number = $match.Groups[1].Value
$key = $citationMap[$number]
if ($key) {
return "\cite{$key}"
} else {
Write-Host "Warning: No mapping for citation $number" -ForegroundColor Yellow
return $match.Value
}
})
# Save the result
$result | Set-Content $outputFile -NoNewline
# Show results
Write-Host "`n✓ Replacement complete!" -ForegroundColor Green
Write-Host "Output: $outputFile" -ForegroundColor Green
Write-Host "`nPreview of replacements:" -ForegroundColor Magenta
$matches = [regex]::Matches($result, '\\cite\{[a-z]+\d{4}[a-z]+\}') | Select-Object -First 3
foreach ($m in $matches) {
Write-Host " $($m.Value)" -ForegroundColor White
}
Step 3: Running the Script
One-Time Setup
If you’ve never run a PowerShell script before, you’ll need to allow it first. Just do this once:
- Press
Windows + Xand click Windows PowerShell (Admin) - Type:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser - Hit
Yand Enter
That’s it. You won’t need to do this again.
Actually Running It
- Save the script above as
replace-citations.ps1— put it wherever you like - Right-click the file and choose Run with PowerShell (or open PowerShell and type
.\replace-citations.ps1) - A file browser pops up — pick your
.texfile - The script creates a new file called
yourfile_updated.texwith all the replacements done
Your original file stays untouched, so there’s no risk of losing anything.
See It in Action
Click to see a Before → After example
Before (input.tex):\documentclass{article}
\begin{document}
Some introductory text about the research topic \cite{1}\cite{2}.
Further discussion on methodology and results \cite{2}, particularly when
applied to analysis and evaluation \cite{1}.
\bibliographystyle{plain}
\bibliography{references}
\end{document}
After (input_updated.tex):
\documentclass{article}
\begin{document}
Some introductory text about the research topic \cite{smith2023keyword}\cite{doe2024analysis}.
Further discussion on methodology and results \cite{doe2024analysis}, particularly when
applied to analysis and evaluation \cite{smith2023keyword}.
\bibliographystyle{plain}
\bibliography{references}
\end{document}
Under the Hood (For the Curious)
You don’t need to understand this part to use the script, but if you’re curious about how it works, here’s a quick breakdown.
The Hashtable
1
2
3
4
$citationMap = @{
'1' = 'smith2023keyword'
'2' = 'doe2024analysis'
}
Think of this as a dictionary. The script looks up each number and finds the matching citation key.
The Regex Pattern
1
$pattern = '\\cite\{(\d+)\}'
This tells the script what to look for:
\\cite— the literal text\cite\{and\}— the curly braces(\d+)— one or more digits (this is what gets captured and replaced)
The Replacement
1
2
3
4
5
6
[regex]::Replace($content, $pattern, {
param($match)
$number = $match.Groups[1].Value
$key = $citationMap[$number]
return "\cite{$key}"
})
For every match, the script grabs the number, looks it up in the dictionary, and swaps it with the real citation key.
What If I Have a Lot of References?
No problem. Just keep adding lines to the mapping:
1
2
3
4
5
6
7
$citationMap = @{
'1' = 'smith2023keyword'
'2' = 'doe2024analysis'
# ... keep going
'50' = 'lee2024algorithms'
'100' = 'wang2023method'
}
The script handles them all the same way, whether you have 5 or 500.
A Few Tips from Experience
Do:
- Always test with a small file first before running it on your full thesis
- Double-check your number-to-key mapping — a wrong mapping means wrong citations
- Use meaningful citation keys like
smith2023keywordinstead of vague ones likeref1
Don’t:
- Reuse the same citation key for different numbers
- Forget the quotes around numbers in the hashtable — write
'1', not1 - Worry if you see a warning — it just means the script couldn’t find a mapping for that number, and it leaves the original citation as-is
Common Issues (and Quick Fixes)
“Scripts are disabled on this system” Run this in PowerShell as Admin:
1
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
“Nothing got replaced”
Check that your citations actually use the \cite{number} format. Also make sure there are no extra spaces inside the braces — \cite{ 1 } won’t match.
“Warning: No mapping for citation X”
You’re using citation number X in your document but haven’t added it to the $citationMap. Either add it or leave it — the script won’t break anything.
Bonus: Combining Multiple Citations
The script handles back-to-back citations just fine:
Click to see an example
Before:Multiple studies \cite{1}\cite{2} have shown...
After:
Multiple studies \cite{smith2023keyword}\cite{doe2024analysis} have shown...
Quick tip: After running the script, you can manually merge these into a single cite command:
Multiple studies \cite{smith2023keyword,doe2024analysis} have shown...
This gives you a cleaner output — [1,2] instead of [1][2].
Wrapping Up
Look, nobody enjoys spending their afternoon doing find-and-replace on citation keys. This script handles it in seconds, and once you’ve set up the mapping, you can reuse it anytime you work with the same bibliography.
Give it a try on your next paper — I think you’ll be surprised how much time it saves.
Ready to Use It?
- Copy the script into a
.ps1file - Update the
$citationMapwith your own citations - Run it on your
.texfile - That’s it — you’re done
Tip: Take a few minutes to get your citation mapping right. It’s worth the upfront effort — it’ll save you hours down the road.
Warning: Always keep a backup of your original
.texfile before running any script on it, especially if it’s your final thesis or dissertation!
Got questions or ran into something unexpected? Drop a comment below — happy to help.